package com.ctshk.rpc.bus.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.ApprovalStatus;
import com.ctshk.common.enums.ChannelMainData;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.IsValidCode;
import com.ctshk.common.enums.ProductType;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.enums.TrainTouristType;
import com.ctshk.common.enums.bus.BusConst;
import com.ctshk.common.enums.bus.BusOnShelfStatusCode;
import com.ctshk.common.enums.bus.BusSaleStatusCode;
import com.ctshk.common.enums.bus.SaleableType;
import com.ctshk.common.enums.bus.SelfSalePermissionTypeCode;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.service.support.BaseService;
import com.ctshk.common.utils.Assist;
import com.ctshk.common.utils.BConst;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.HktOrderUtil;
import com.ctshk.common.utils.RlgOrderUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.bus.dto.BusB2CRecommendedDTO;
import com.ctshk.rpc.bus.dto.BusPriceRemainderDTO;
import com.ctshk.rpc.bus.dto.BusProductCostDTO;
import com.ctshk.rpc.bus.dto.BusProductCostDateDTO;
import com.ctshk.rpc.bus.dto.BusProductCostPriceDTO;
import com.ctshk.rpc.bus.dto.BusProductDTO;
import com.ctshk.rpc.bus.dto.BusProductPageDTO;
import com.ctshk.rpc.bus.dto.BusProductReservationAgentDTO;
import com.ctshk.rpc.bus.dto.BusProductReservationSettingsDTO;
import com.ctshk.rpc.bus.dto.BusProductStrategyByChannelDTO;
import com.ctshk.rpc.bus.dto.BusProductStrategyDTO;
import com.ctshk.rpc.bus.dto.BusReservationAgentDTO;
import com.ctshk.rpc.bus.dto.BusSeatDTO;
import com.ctshk.rpc.bus.dto.Constants;
import com.ctshk.rpc.bus.dto.RecommendedBusDTO;
import com.ctshk.rpc.bus.dto.ReservationBusPageDTO;
import com.ctshk.rpc.bus.dto.es.BusProductCacheDTO;
import com.ctshk.rpc.bus.entity.BusInitializationSettings;
import com.ctshk.rpc.bus.entity.BusLine;
import com.ctshk.rpc.bus.entity.BusLineSeat;
import com.ctshk.rpc.bus.entity.BusProduct;
import com.ctshk.rpc.bus.entity.BusProductChannelOfflineAgentCustom;
import com.ctshk.rpc.bus.entity.BusProductChannelOfflineSelfCustom;
import com.ctshk.rpc.bus.entity.BusProductChannelOnlineSelfPlatform;
import com.ctshk.rpc.bus.entity.BusProductCost;
import com.ctshk.rpc.bus.entity.BusProductCostDate;
import com.ctshk.rpc.bus.entity.BusProductCostPrice;
import com.ctshk.rpc.bus.entity.BusProductIncreaseStrategyRule;
import com.ctshk.rpc.bus.entity.BusProductReservationSettings;
import com.ctshk.rpc.bus.entity.BusProductSeat;
import com.ctshk.rpc.bus.entity.BusProductSold;
import com.ctshk.rpc.bus.entity.BusProductStrategy;
import com.ctshk.rpc.bus.entity.BusProductStrategyDate;
import com.ctshk.rpc.bus.mapper.BusInitializationSettingsMapper;
import com.ctshk.rpc.bus.mapper.BusLineMapper;
import com.ctshk.rpc.bus.mapper.BusLineSeatMapper;
import com.ctshk.rpc.bus.mapper.BusProductChannelOfflineAgentCustomMapper;
import com.ctshk.rpc.bus.mapper.BusProductChannelOfflineSelfCustomMapper;
import com.ctshk.rpc.bus.mapper.BusProductChannelOnlineSelfPlatformMapper;
import com.ctshk.rpc.bus.mapper.BusProductCostDateMapper;
import com.ctshk.rpc.bus.mapper.BusProductCostMapper;
import com.ctshk.rpc.bus.mapper.BusProductCostPriceMapper;
import com.ctshk.rpc.bus.mapper.BusProductIncreaseStrategyRuleMapper;
import com.ctshk.rpc.bus.mapper.BusProductMapper;
import com.ctshk.rpc.bus.mapper.BusProductReservationSettingsMapper;
import com.ctshk.rpc.bus.mapper.BusProductSeatMapper;
import com.ctshk.rpc.bus.mapper.BusProductSoldMapper;
import com.ctshk.rpc.bus.mapper.BusProductStrategyDateMapper;
import com.ctshk.rpc.bus.mapper.BusProductStrategyMapper;
import com.ctshk.rpc.bus.req.BatchBusProductInfoReq;
import com.ctshk.rpc.bus.req.BusB2CRecommendedListQueryReq;
import com.ctshk.rpc.bus.req.BusIncreaseStrategyPriceQueryReq;
import com.ctshk.rpc.bus.req.BusProductAddApprovalReq;
import com.ctshk.rpc.bus.req.BusProductCostDateReq;
import com.ctshk.rpc.bus.req.BusProductCostPriceReq;
import com.ctshk.rpc.bus.req.BusProductCostReq;
import com.ctshk.rpc.bus.req.BusProductListForIotcQueryReq;
import com.ctshk.rpc.bus.req.BusProductQueryReq;
import com.ctshk.rpc.bus.req.BusProductReq;
import com.ctshk.rpc.bus.req.BusProductReservationAgentQueryReq;
import com.ctshk.rpc.bus.req.BusProductReservationSettingsReq;
import com.ctshk.rpc.bus.req.BusProductSetReq;
import com.ctshk.rpc.bus.req.BusshiftReq;
import com.ctshk.rpc.bus.req.ReservationBusDetailReq;
import com.ctshk.rpc.bus.req.ReservationBusPageReq;
import com.ctshk.rpc.bus.service.IBusProductService;
import com.ctshk.rpc.order.bus.service.IBusOrderService;
import com.ctshk.rpc.system.dto.SysAgentQueryListDTO;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.req.SysAgentQueryListReq;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.ISysAgentService;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;

/**
 * <p>
 * 巴士产品表 服务实现类
 * </p>
 *
 * @author 彭柳霖
 * @since 2021-02-08
 */
@DubboService
public class BusProductServiceImpl extends ServiceImpl<BusProductMapper, BusProduct> implements IBusProductService, BaseService {

    @Autowired
    private BusProductMapper busProductMapper;
    @Autowired
    private BusProductSeatMapper busProductSeatMapper;
    @Autowired
    private BusLineMapper busLineMapper;
    @Autowired
    private BusLineSeatMapper busLineSeatMapper;
    @Autowired
    private BusProductSoldMapper soldMapper;
    @Autowired
    private BusProductCostMapper busProductCostMapper;
    @Autowired
    private BusProductCostDateMapper busProductCostDateMapper;
    @Autowired
    private BusProductCostPriceMapper busProductCostPriceMapper;
    @Autowired
    private BusProductReservationSettingsMapper busProductReservationSettingsMapper;
    @Autowired
    private BusProductStrategyMapper busProductStrategyMapper;
    @Autowired
    private BusProductStrategyDateMapper busProductStrategyDateMapper;
    @Autowired
    private BusProductIncreaseStrategyRuleMapper ruleMapper;
    @Autowired
    private BusProductChannelOnlineSelfPlatformMapper platformMapper ;
    @Autowired
    private BusProductChannelOfflineSelfCustomMapper busProductChannelOfflineSelfCustomMapper;
    @Autowired
    private BusProductChannelOfflineAgentCustomMapper busProductChannelOfflineAgentCustomMapper;
    @Autowired
    private BusInitializationSettingsMapper busInitializationSettingsMapper;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @DubboReference
    private ISysAgentService sysAgentService;
    @DubboReference
    ISysUserService sysUserService;
    @DubboReference
    ISysApprovalService sysApprovalService;
    @Autowired
    BusProductSoldMapper busProductSoldMapper;
    @DubboReference
    IBusOrderService busOrderService;
    
    @DubboReference
    IMainDataCurrencyService mainDataCurrencyService;
    
    @DubboReference
    ISysPermissionService sysPermissionService;
    
    @Autowired
    BusProductChannelOnlineSelfPlatformMapper busProductChannelOnlineSelfPlatformMapper;

    /**
     * 分页查询巴士产品列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BusProductPageDTO>> queryList(BusProductQueryReq req, TokenUser tokenUser) {
    	//临时做法，默认填充菜单ID
    	if (req.getMenuId() == null) {
    		req.setMenuId(36389833018441728l);
    	}
    	//数据权限
    	List<Long> permissionUserList = sysPermissionService.queryPermission(req.getMenuId(), getTokenUserId(tokenUser)).ok();
    	
    	IPage<BusProduct> page = busProductMapper.queryProductList(req, permissionUserList);
        List<BusProductPageDTO> list = Assist.toBeanList(page.getRecords(), BusProductPageDTO.class);

        Assist.forEach(list, dto -> {
            if (dto.getLineId() != null) {
                BusLine busLine = busLineMapper.selectById(dto.getLineId());
                if (busLine != null) {
                    dto.setGatewayName(busLine.getGatewayName());
                }
            }
        });

        return newPageResult(page, list);
    }

    /**
     * 新增巴士产品信息
     *
     * @param busProductReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result saveBusProduct(BusProductReq busProductReq, TokenUser user) {
        Result checkResult = checkProductReq(busProductReq, user);
        if (!Objects.isNull(checkResult)) {
            return checkResult;
        }

        Result result = checkCostateResult(busProductReq.getBusProductCostReqList());
        if (!Objects.isNull(result)) {
            return result;
        }

        //巴士产品修改
        if (busProductReq.getId() != null) {
        	//巴士产品修改，先删除后新增
        	busProductMapper.deleteById(busProductReq.getId());
        	busProductSeatMapper.delete(new QueryWrapper<BusProductSeat>().lambda().eq(BusProductSeat::getProductId, busProductReq.getId()));

        	List<BusProductCost> busProductCostLists = busProductCostMapper.
        			selectList(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProductReq.getId()));

        	for (BusProductCost busProductCost : busProductCostLists) {
        		busProductCostDateMapper.delete(new QueryWrapper<BusProductCostDate>().lambda().eq(BusProductCostDate::getCostId, busProductCost.getId()));
        		busProductCostPriceMapper.delete(new QueryWrapper<BusProductCostPrice>().lambda().eq(BusProductCostPrice::getCostId, busProductCost.getId()));
        	}
        	busProductCostMapper.delete(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProductReq.getId()));
//        	busProductReservationSettingsMapper.delete(new QueryWrapper<BusProductReservationSettings>().lambda().eq(BusProductReservationSettings::getBusProductId, busProductReq.getId()));
        }


        return this.addProductInfo(busProductReq, user);

    }

    /**
     * 新增巴士产品预订信息
     *
     * @param reservationSettingsReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result saveReservation(BusProductReservationSettingsReq reservationSettingsReq, TokenUser user) {

        //保存巴士产品预订设置信息
        Long[] busProductIds = reservationSettingsReq.getBusProductIds();
        for (Long busProductId : busProductIds) {
            BusProduct busProduct = busProductMapper.selectById(busProductId);
            if (Objects.isNull(busProduct)) {
                throw new BusinessException(SystemError.BUS_PRODUCT_9009);
            }

            BusProductReservationSettings busProductReservationSettings = EntityUtil.copy(reservationSettingsReq, BusProductReservationSettings.class);
            busProductReservationSettings.setBusProductId(busProductId);
            busProductReservationSettings.setId(SnowflakeIdWorker.nextId());
            busProductReservationSettingsMapper.insert(busProductReservationSettings);

            if (reservationSettingsReq.getSaveType() == 1) {
                busProduct.setApprovalStatus(ApprovalStatus.WAIT_SUBMIT.getCode());
                busProductMapper.updateById(busProduct);
            } else {
                busProduct.setApprovalStatus(ApprovalStatus.REVIEWING.getCode());
                sysApprovalService.start(SystemBusinessType.BUS_TICKET.getCode(), SysApprovalType.ADD_BUS.getCode()
                        , busProduct.getId(), user.getId(), null, null).ok();
                busProductMapper.updateById(busProduct);
            }
        }

        if (reservationSettingsReq.getSaveType() == 1) {
            //保存
            return Result.success(1);
        } else {
            //提交保存
            return Result.success(2);

        }

    }

    /**
     * 修改巴士产品预订信息
     *
     * @param reservationSettingsReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result updateReservation(BusProductReservationSettingsReq reservationSettingsReq, TokenUser user) {
        //更新巴士产品预订设置信息
        Long[] busProductIds = reservationSettingsReq.getBusProductIds();
        for (Long busProductId : busProductIds) {
            BusProduct busProduct = busProductMapper.selectById(busProductId);
            if (Objects.isNull(busProduct)) {
                throw new BusinessException(SystemError.BUS_PRODUCT_9009);
            }
            BusProductReservationSettings busProductReservationSettings = EntityUtil.copy(reservationSettingsReq, BusProductReservationSettings.class);
            busProductReservationSettingsMapper.updateById(busProductReservationSettings);
        }

        return Result.success();
    }

    /**
     * 新增-编辑提交审批
     *
     * @param id
     * @param user
     */
    @Override
    public Result submit(Long id, TokenUser user) {
        BusProduct busProduct = baseMapper.selectById(id);
        if (Objects.isNull(busProduct)) {
            return Result.failed(SystemError.BUS_PRODUCT_9009);
        }
        //非待提交状态不能进行审批
        if (!ApprovalStatus.WAIT_SUBMIT.getCode().equals(busProduct.getApprovalStatus())) {
            return Result.failed(SystemError.BUS_PRODUCT_9028);
        }
        busProduct.setApprovalStatus(ApprovalStatus.REVIEWING.getCode());
        busProduct.setModifiedId(user.getId());
        busProduct.setGmtModified(LocalDateTime.now());
        baseMapper.updateById(busProduct);

        sysApprovalService.start(SystemBusinessType.BUS_TICKET.getCode(), SysApprovalType.ADD_BUS.getCode()
                , busProduct.getId(), user.getId(), null, null).ok();
        return Result.success();
    }

    /**
     * 修改审核通过巴士产品
     *
     * @param busProductReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result updateApprovedBusProduct(BusProductReq busProductReq, TokenUser user) {

        Result checkResult = checkProductReq(busProductReq, user);
        if (!Objects.isNull(checkResult)) {
            return checkResult;
        }

        Result result = checkCostateResult(busProductReq.getBusProductCostReqList());
        if (!Objects.isNull(result)) {
            return result;
        }

        List<String> shiftCodeList = new ArrayList<>();
        List<LocalTime> departureTimeList = new ArrayList<>();

        BusshiftReq[] busshiftReqs = busProductReq.getBusshiftReqs();
        for (BusshiftReq busshiftReq : busshiftReqs) {
            shiftCodeList.add(busshiftReq.getShiftCode());
            departureTimeList.add(busshiftReq.getDepartureTime());
        }

        List<Long> busProductIdList = new ArrayList<>();


        //更新巴士产品信息
        BusProduct busProduct = busProductMapper.selectById(busProductReq.getId());
        if (Objects.isNull(busProduct)) {
            return Result.failed(SystemError.BUS_PRODUCT_9009);
        }
        if (!ApprovalStatus.REVIEW_YES.getCode().equals(busProduct.getApprovalStatus())) {
            return Result.failed(SystemError.BUS_PRODUCT_9025);
        }

        if (IsValidCode.VALID.getCode().equals(busProduct.getSaleStatus())) {
            return Result.failed(SystemError.TRAIN_PRODUCT_9029);
        }
        busProductIdList.add(busProduct.getId());


        BeanUtils.copyProperties(busProductReq, busProduct);
        busProduct.setShiftCode(shiftCodeList.get(0));
        busProduct.setDepartureTime(departureTimeList.get(0));
        busProduct.setModifiedId(user.getId());
        busProduct.setGmtModified(LocalDateTime.now());
        busProductMapper.updateById(busProduct);


        //更新巴士产品座位表(先删后插入)
        busProductSeatMapper.delete(new QueryWrapper<BusProductSeat>().lambda().eq(BusProductSeat::getProductId, busProduct.getId()));
        String seatNumbers = busProductReq.getSeatNumbers();
        List<String> seatNumbersList = Arrays.asList(seatNumbers.split(","));
        seatNumbersList.forEach(seatNumber -> {
            BusProductSeat busProductSeat = new BusProductSeat();
            busProductSeat.setId(SnowflakeIdWorker.nextId());
            busProductSeat.setProductId(busProduct.getId());
            busProductSeat.setSeatNumber(seatNumber);
            busProductSeatMapper.insert(busProductSeat);
        });

        //查询巴士产品成本信息
        List<BusProductCost> busProductCostLists = busProductCostMapper.selectList(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProduct.getId()));

        //更新巴士产品成本相关信息- 先删后插入
        for (BusProductCost busProductCost : busProductCostLists) {
            busProductCostDateMapper.delete(new QueryWrapper<BusProductCostDate>().lambda().eq(BusProductCostDate::getCostId, busProductCost.getId()));
            busProductCostPriceMapper.delete(new QueryWrapper<BusProductCostPrice>().lambda().eq(BusProductCostPrice::getCostId, busProductCost.getId()));
        }
        busProductCostMapper.delete(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProduct.getId()));


        //保存巴士产品成本信息
        List<BusProductCostReq> busProductCostReqList = busProductReq.getBusProductCostReqList();
        for (BusProductCostReq busProductCostReq : busProductCostReqList) {
            //保存巴士产品成本
            BusProductCost busProductCost = new BusProductCost();
            BeanUtils.copyProperties(busProductCostReq, busProductCost);
            Long costId = SnowflakeIdWorker.nextId();
            busProductCost.setId(costId);
            busProductCost.setBusProductId(busProduct.getId());
            busProductCostMapper.insert(busProductCost);

            //保存巴士产品成本日期
            List<BusProductCostDateReq> busProductCostDateReqList = busProductCostReq.getBusProductCostDateReqList();
            for (BusProductCostDateReq busProductCostDateReq : busProductCostDateReqList) {
                BusProductCostDate busProductCostDate = new BusProductCostDate();
                BeanUtils.copyProperties(busProductCostDateReq, busProductCostDate);
                busProductCostDate.setId(SnowflakeIdWorker.nextId());
                busProductCostDate.setCostId(costId);
                busProductCostDateMapper.insert(busProductCostDate);
            }

            //保存巴士产品成本价格
            List<BusProductCostPriceReq> busProductCostPriceReqList = busProductCostReq.getBusProductCostPriceReqList();
            for (BusProductCostPriceReq busProductCostPriceReq : busProductCostPriceReqList) {
                BusProductCostPrice busProductCostPrice = new BusProductCostPrice();
                BeanUtils.copyProperties(busProductCostPriceReq, busProductCostPrice);
                busProductCostPrice.setId(SnowflakeIdWorker.nextId());
                busProductCostPrice.setCostId(costId);
                busProductCostPriceMapper.insert(busProductCostPrice);
            }
        }

        return Result.success(busProductIdList);
    }


    /**
     * 修改审核不通过巴士产品
     *
     * @param busProductReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result updateUnapprovedBusProduct(BusProductReq busProductReq, TokenUser user) {

        Result checkResult = checkProductReq(busProductReq, user);
        if (!Objects.isNull(checkResult)) {
            return checkResult;
        }

        Result result = checkCostateResult(busProductReq.getBusProductCostReqList());
        if (!Objects.isNull(result)) {
            return result;
        }

        BusProduct busProduct = busProductMapper.selectById(busProductReq.getId());
        if (Objects.isNull(busProduct)) {
            return Result.failed(SystemError.BUS_PRODUCT_9009);
        }

        if (!ApprovalStatus.REVIEW_NO.getCode().equals(busProduct.getApprovalStatus())
                && !ApprovalStatus.WAIT_SUBMIT.getCode().equals(busProduct.getApprovalStatus())) {
            return Result.failed(SystemError.BUS_PRODUCT_9026);
        }
//        if (IsValidCode.VALID.getCode().equals(busProduct.getSaleStatus())) {
//            return Result.failed(SystemError.TRAIN_PRODUCT_9029);
//        }

        //审核不通过修改 等同于新增(必须先删后新增)
        busProductMapper.deleteById(busProductReq.getId());
        busProductSeatMapper.delete(new QueryWrapper<BusProductSeat>().lambda().eq(BusProductSeat::getProductId, busProductReq.getId()));

        List<BusProductCost> busProductCostLists = busProductCostMapper.
                selectList(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProductReq.getId()));

        for (BusProductCost busProductCost : busProductCostLists) {
            busProductCostDateMapper.delete(new QueryWrapper<BusProductCostDate>().lambda().eq(BusProductCostDate::getCostId, busProductCost.getId()));
            busProductCostPriceMapper.delete(new QueryWrapper<BusProductCostPrice>().lambda().eq(BusProductCostPrice::getCostId, busProductCost.getId()));
        }
        busProductCostMapper.delete(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProductReq.getId()));
        busProductReservationSettingsMapper.delete(new QueryWrapper<BusProductReservationSettings>().lambda().eq(BusProductReservationSettings::getBusProductId, busProductReq.getId()));
        //审核不通过的产品 调用新增方法
        return this.addProductInfo(busProductReq, user);

    }


    /**
     * 查询巴士产品详情信息
     *
     * @param id 产品id
     * @return
     */
    @Override
    public BusProductDTO queryDetail(Long id) {
        BusProductDTO busProductDto = new BusProductDTO();
        BusProduct busProduct = busProductMapper.selectById(id);

        if (busProduct != null) {
            BeanUtils.copyProperties(busProduct, busProductDto);


            BusLine busline = busLineMapper.selectById(busProduct.getLineId());
            if (!Objects.isNull(busline)) {
                busProductDto.setVehicleType(busline.getVehicleType());
                busProductDto.setEstimatedTime(busline.getEstimatedTime());
                busProductDto.setGatewayName(busline.getGatewayName());
                busProductDto.setLineName(busline.getLineName());
            }
        }


        //查询巴士产品座位信息
        List<BusProductSeat> busProductSeatList = busProductSeatMapper.selectList(new QueryWrapper<BusProductSeat>().lambda().eq(BusProductSeat::getProductId, id));
        String seatNumbers = busProductSeatList.stream().map(n -> n.getSeatNumber()).collect(Collectors.joining(","));
        busProductDto.setSeatNumbers(seatNumbers);
        busProductDto.setSeatNumberList(Assist.forEachToList(busProductSeatList, BusProductSeat::getSeatNumber));

        //查询巴士产品成本信息(包括日期和价格)
        List<BusProductCostDTO> busProductCostList = busProductCostMapper.queryList(id);

        for (BusProductCostDTO busProductCostDTO : busProductCostList) {
            List<BusProductCostDateDTO> busProductCostDateDTOList = busProductCostDateMapper.queryList(busProductCostDTO.getId());
            List<BusProductCostPriceDTO> busProductCostPriceDTOList = busProductCostPriceMapper.queryList(busProductCostDTO.getId());
            busProductCostDTO.setBusProductCostDateDtoList(busProductCostDateDTOList);
            busProductCostDTO.setBusProductCostPriceDtoList(busProductCostPriceDTOList);
            
            if (busProductCostDTO.getCurrencyId() != null) {
            	BigDecimal rate = mainDataCurrencyService.getPlanneRateById(busProductCostDTO.getCurrencyId());
            	busProductCostDTO.setExchangeRate(rate);
            }
        }
        busProductDto.setBusProductCostDtoList(busProductCostList);

        //查询巴士产品预订信息
        List<BusProductReservationSettingsDTO> busProductReservationSettingsDtoList = busProductReservationSettingsMapper.queryList(id);
        if (!CollectionUtils.isEmpty(busProductReservationSettingsDtoList)) {
            busProductDto.setBusProductReservationSettingsDto(busProductReservationSettingsDtoList.get(0));
        }
        return busProductDto;
    }

    /**
     * 查询巴士线路座位信息
     *
     * @param lineId
     * @return
     */
    @Override
    public BusSeatDTO querySeats(Long lineId) {
        BusLine busLine = busLineMapper.selectById(lineId);
        List<BusLineSeat> BusLineSeatList = busLineSeatMapper.selectList(new QueryWrapper<BusLineSeat>().lambda().eq(BusLineSeat::getLineId, busLine.getId()));
        String seatNumbers = BusLineSeatList.stream().map(n -> n.getSeatNumber()).collect(Collectors.joining(","));
        BusSeatDTO busSeatDTO = new BusSeatDTO();
        busSeatDTO.setSeats(seatNumbers);
        return busSeatDTO;
    }


    /**
     * api设置
     *
     * @param busProductSetReq
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result setApi(BusProductSetReq busProductSetReq, TokenUser user) {
        BusProduct busProduct = busProductMapper.selectById(busProductSetReq.getId());
        if (Objects.isNull(busProduct)) {
            return Result.failed(SystemError.BUS_PRODUCT_9009);
        }
        //是API产品才可以设置
        if (Constants.API.equals(busProduct.getProductSource())) {
            busProduct.setPackStatus(busProductSetReq.getPackStatus());
            busProduct.setPriceType(busProductSetReq.getPriceType());
            busProduct.setPrice(busProductSetReq.getPrice());
            busProduct.setChargePersonId(busProductSetReq.getChargePersonId());
            busProduct.setChargePersonName(busProductSetReq.getChargePersonName());
            busProduct.setModifiedId(user.getId());
            busProduct.setGmtModified(LocalDateTime.now());
            busProductMapper.updateById(busProduct);
        } else {
            return Result.failed(SystemError.BUS_PRODUCT_9010);
        }

        return Result.success();

    }

    /**
     * 有效无效设置
     *
     * @param id
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result setValid(Long id, TokenUser user) {
        BusProduct busProduct = busProductMapper.selectById(id);
        if (Objects.isNull(busProduct)) {
            return Result.failed(SystemError.BUS_PRODUCT_9009);
        }
//        //只有API产品 或已审批的人工录入产品才能设置有效
//        if (ProductType.API_PRODUCT.getCode().equals(busProduct.getProductSource()) ||
//                (ProductType.MANUAL_ENTRY.getCode().equals(busProduct.getProductSource()) && ApprovalStatus.REVIEW_YES.getCode().equals(busProduct.getApprovalStatus()))) {

        if (IsValidCode.VALID.getCode().equals(busProduct.getSaleStatus())) {
        	busProduct.setSaleStatus(IsValidCode.IN_VALID.getCode()); //设置为无效
        } else {
        	busProduct.setSaleStatus(IsValidCode.VALID.getCode()); //设置为有效
        }
        busProduct.setModifiedId(user.getId());
        busProduct.setGmtModified(LocalDateTime.now());
        busProductMapper.updateById(busProduct);
//        } else {
//            return Result.failed(SystemError.BUS_PRODUCT_9013);
//        }
        return Result.success();
    }

    /**
     * 批量设置
     *
     * @param batchBusProductInfoReq
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result batchSetting(BatchBusProductInfoReq batchBusProductInfoReq, TokenUser user) {
        if (Objects.isNull(user)) {
            return Result.failed(SystemError.USER_1000);
        }
        if (Objects.isNull(batchBusProductInfoReq)
                || CollectionUtils.isEmpty(batchBusProductInfoReq.getBusProductIds())) {
            return Result.failed(SystemError.BUS_PRODUCT_9004);
        }
        List<BusProduct> busProductList = busProductMapper.selectList(new QueryWrapper<BusProduct>().lambda().in(BusProduct::getId, batchBusProductInfoReq.getBusProductIds()));
        
        //负责人信息
        UserDTO chargePersonDto = null;
        if (batchBusProductInfoReq.getChargePersonId() != null) {
        	chargePersonDto = sysUserService.queryCacheUser(batchBusProductInfoReq.getChargePersonId());
        	notNull(chargePersonDto, SystemError.USER_1002);
        }

        //判断产品来源是否相同
        if (!CollectionUtils.isEmpty(busProductList)) {
            for (BusProduct busProduct : busProductList) {
                if (!busProductList.get(0).getProductSource().equals(busProduct.getProductSource())) {
                    return Result.failed(SystemError.BUS_PRODUCT_9011);
                }
                if (ProductType.MANUAL_ENTRY.getCode().equals(busProduct.getProductSource()) &&
                        !ApprovalStatus.REVIEW_YES.getCode().equals(busProduct.getApprovalStatus())) {
                    return Result.failed(SystemError.TRAIN_PRODUCT_14012);
                }
            }
            for (BusProduct busProduct : busProductList) {
                busProduct.setPackStatus(batchBusProductInfoReq.getPackStatus());
                busProduct.setSaleStatus(batchBusProductInfoReq.getSaleStatus());
                busProduct.setModifiedId(user.getId());
                busProduct.setGmtModified(LocalDateTime.now());
                
                if (chargePersonDto != null) {
                	busProduct.setChargePersonId(chargePersonDto.getId());
                	busProduct.setChargePersonNumber(chargePersonDto.getEmployeeNumber());
                	busProduct.setChargePersonName(chargePersonDto.getFullName());
                	busProduct.setChargePersonDepartment(chargePersonDto.getDept());;
                }
                busProductMapper.updateById(busProduct);
            }
        }

        return Result.success();
    }

    /**
     * 推荐设置
     *
     * @param id
     */
    @Override
    public Result setRecommended(Long id, TokenUser user) {
        BusProduct busProduct = busProductMapper.selectById(id);
        if (Objects.isNull(busProduct)) {
            return Result.failed(SystemError.BUS_PRODUCT_9009);
        }

        if (Constants.RECOMMENDED.equals(busProduct.getRecommendationStatus())) {
            busProduct.setRecommendationStatus(Constants.UN_RECOMMENDED); //设置为不推荐
        } else {
            busProduct.setRecommendationStatus(Constants.RECOMMENDED); //设置为推荐
        }
        busProduct.setModifiedId(user.getId());
        busProduct.setGmtModified(LocalDateTime.now());
        busProductMapper.updateById(busProduct);
        return Result.success();
    }

    /**
     * 查询巴士票推荐列表
     */
    @Override
    public List<RecommendedBusDTO> queryRecommendedBusTicket(Long userId) {
        LocalDate nowDate = LocalDate.now();
        List<RecommendedBusDTO> recommendedBusDTOList = busProductMapper.queryRecommendedBusTicket();
        if (CollectionUtils.isEmpty(recommendedBusDTOList)) {
            return null;
        }
        for (RecommendedBusDTO recommendedBusDTO : recommendedBusDTOList) {
        	//查询巴士产品售价信息 - 线下自营
            BusPriceRemainderDTO busPriceRemainderDTO = findBusSalePriceInfoOfflineSelf(recommendedBusDTO.getBusProductId(), nowDate, userId);
            recommendedBusDTO.setPrice(busPriceRemainderDTO.getAdultPrice());
        }
        return recommendedBusDTOList;
    }

    /**
     * 巴士票预订查询
     *
     * @param req
     * @return
     */
    @Override
    public PageResponse<ReservationBusPageDTO> queryReservationBusList(ReservationBusPageReq req, Long userId) {
    	if (Assist.lt(req.getQueryDate(), LocalDate.now())) {
    		throwException(SystemError.BUS_ORDER_9023);
    	}
    	
        //拼接余位条件
        req.setInventory(Assist.add(req.getPassengerAdultNum(), req.getPassengerChildrenNum(), req.getPassengerOldNum()));

        IPage<ReservationBusPageDTO> agentPage = new Page<>(req.getPageNo(), req.getPageSize());
        agentPage = busProductMapper.queryReservationBusList(req, agentPage);

        List<ReservationBusPageDTO> reservationBusPageDTOList = agentPage.getRecords();
        if (CollectionUtils.isEmpty(reservationBusPageDTOList)) {
            return null;
        }
        for (ReservationBusPageDTO busPageDTO : reservationBusPageDTOList) {
            packBusDetailInfo(busPageDTO, req.getQueryDate(), userId, req.getAgentId());
        }

        PageResponse<ReservationBusPageDTO> result = new PageResponse<>(agentPage.getRecords(), agentPage.getCurrent() == 1,
                agentPage.getTotal() <= (agentPage.getCurrent() * agentPage.getSize()),
                agentPage.getTotal(), agentPage.getCurrent(), agentPage.getSize());
        return result;

    }

    /**
     * 巴士票预订详情
     *
     * @return
     */
    @Override
    public Result<ReservationBusPageDTO> queryReservationBusDetail(ReservationBusDetailReq req, TokenUser tokenUser) {
        ReservationBusPageDTO dto = busProductMapper.queryReservationBusDetail(req.getId());
        if (dto != null) {
            packBusDetailInfo(dto, req.getQueryDate(), getTokenUserId(tokenUser), req.getAgentId());
        }
        return newResult(dto);
    }

    /**
     * 封闭预订详情数据
     *
     * @param busPageDTO
     * @param userId
     */
    private void packBusDetailInfo(ReservationBusPageDTO busPageDTO, LocalDate queryDate, Long userId, Long agentId) {
    	notNull(busPageDTO.getCurrencyId(), SystemError.AIREXPRESS_ORDER_60029);
    	
        if (queryDate == null) {
        	queryDate = LocalDate.now();
        }

        BusPriceRemainderDTO busPriceRemainderDTO = null;
        //查询巴士产品售价信息 - 线下代理
        if (agentId != null) {
        	busPriceRemainderDTO = findBusSalePriceInfoOfflineAgent(busPageDTO.getBusProductId(), queryDate, agentId);
        } else {  //查询巴士产品售价信息 - 线下自营
        	busPriceRemainderDTO = findBusSalePriceInfoOfflineSelf(busPageDTO.getBusProductId(), queryDate, userId);
        }
        
        busPageDTO.setAdultPrice(busPriceRemainderDTO.getAdultPrice());
        busPageDTO.setChildrenPrice(busPriceRemainderDTO.getChildrenPrice());
        busPageDTO.setOldPrice(busPriceRemainderDTO.getOldPrice());
        busPageDTO.setTicketNum(busPriceRemainderDTO.getRemainderNumber());
        busPageDTO.setIsLimitTicket(busPriceRemainderDTO.getIsLimitTicket());

        //预订设置信息
        List<BusProductReservationSettingsDTO> busProductReservationSettingsDtoList = busProductReservationSettingsMapper.queryList(busPageDTO.getBusProductId());
        BusProductReservationSettingsDTO settingsDto = Assist.findFirst(busProductReservationSettingsDtoList);
        if (settingsDto != null) {
            busPageDTO.setIsConfirm(settingsDto.getIsConfirm());
            busPageDTO.setBookingInformation(settingsDto.getBookingInformation());
            busPageDTO.setChangeSettings(settingsDto.getChangeSettings());
        }
    }
    
    /**
     * 计算余票数
     * @param ruleEntity
     * @param busProduct
     * @param queryDate
     */
    private int calcRemainderNum(BusProductIncreaseStrategyRule ruleEntity, BusProduct busProduct, LocalDate queryDate) {
    	return calcRemainderNum(ruleEntity, busProduct.getId(), busProduct.getInventory(), queryDate);
    }
    
    /**
     * 计算余票数
     * @param ruleEntity
     * @param busProductId
     * @param inventory
     * @param queryDate
     */
    private int calcRemainderNum(BusProductIncreaseStrategyRule ruleEntity, Long busProductId, Integer inventory, LocalDate queryDate) {
    	int remainderNum = 0;

        if (ruleEntity != null) {
            //有限制可售数量
            if (Constants.SALE_TYPE_LIMIT.equals(ruleEntity.getSaleableType())) {
                remainderNum = Assist.defaultInt(ruleEntity.getSaleableNumber());
            } else {  //无限制可售数量
                remainderNum = Assist.defaultInt(inventory);
            }

            //巴士产品已售信息
            BusProductSold entity = busProductSoldMapper.selectOneByKey("bus_product", busProductId, "sale_date", queryDate);
            if (entity != null && entity.getSoldNumber() != null) {
                remainderNum -= entity.getSoldNumber();
            }
        }

        if (remainderNum < 0) {
            remainderNum = 0;
        }

        return remainderNum;
	}
    
    /**
     * 计算余票数
     */
    private int calcRemainderNum(int saleableNumber, Long busProductId, LocalDate queryDate) {
    	//巴士产品已售信息
    	BusProductSold entity = busProductSoldMapper.selectOneByKey("bus_product", busProductId, "sale_date", queryDate);
    	if (entity != null && entity.getSoldNumber() != null) {
    		saleableNumber -= entity.getSoldNumber();
    	}

        if (saleableNumber < 0) {
        	saleableNumber = 0;
        }

        return saleableNumber;
	}

    @Override
    public Result<List<BusReservationAgentDTO>> selectReservationAgentListById(Long id) {
        if (Objects.isNull(id)) {
            throw new BusinessException(SystemError.BUS_PRODUCT_9004);
        }
        //查询巴士产品
        BusProduct busProduct = busProductMapper.selectById(id);
        if (Objects.isNull(busProduct)) {
            throw new BusinessException(SystemError.BUS_PRODUCT_9009);
        }
        List<BusReservationAgentDTO> reservationAgentDTOList = new ArrayList<>();
        BusProductIncreaseStrategyRule busIncreaseStrategyRule = null;

        // 查询巴士-当前日期加幅策略
        BusProductStrategyDTO busProductStrategyDTO = busProductStrategyMapper.queryBusProductStrategyInfo(id, LocalDate.now());
        if (busProductStrategyDTO != null) {
            // 代理禁售
            if (busProductStrategyDTO.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                return Result.success(null);
            } else if (busProductStrategyDTO.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                // 当前巴士-线下自营所有-获取加幅规则
                busIncreaseStrategyRule = ruleMapper.selectById(busProductStrategyDTO.getAgentSalePermissionId());
                int remainderNumber = buildRemainderNumber(busIncreaseStrategyRule);
                if (busIncreaseStrategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT && remainderNumber == 0) {
                    // 余票为0，代理商加幅规则失效
                    busIncreaseStrategyRule = null;
                } else {
                    // 获取所有代理商
                    List<SysAgentQueryListDTO> sysBigClientQueryListDTOs = getSysBigClientQueryListDTOS();
                    if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(sysBigClientQueryListDTOs)) {
                        for (SysAgentQueryListDTO sysBigClientQueryListDTO : sysBigClientQueryListDTOs) {
                            BusReservationAgentDTO busReservationAgentDTO = new BusReservationAgentDTO();
                            busReservationAgentDTO.setId(sysBigClientQueryListDTO.getId());
                            busReservationAgentDTO.setAgentName(sysBigClientQueryListDTO.getGroupCnName());
                            busReservationAgentDTO.setSaleableType(busIncreaseStrategyRule.getSaleableType());
                            busReservationAgentDTO.setRemainderNumber(remainderNumber);

                            addeAgentAdultPrice(busReservationAgentDTO,
                                    busIncreaseStrategyRule.getPriceType(), busIncreaseStrategyRule.getPrice());
                            addeAgentChildRenPrice(busReservationAgentDTO,
                                    busIncreaseStrategyRule.getPriceType(), busIncreaseStrategyRule.getPrice());
                            reservationAgentDTOList.add(busReservationAgentDTO);
                        }
                    }
                }
            } else if (busProductStrategyDTO.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                // 获取所有代理商
                List<SysAgentQueryListDTO> sysBigClientQueryListDTOs = getSysBigClientQueryListDTOS();
                //当前巴士-线下代理选中-获取代理加幅规则列表
                QueryWrapper<BusProductChannelOfflineAgentCustom> offlineAgentQueryWrapper = new QueryWrapper<>();
                offlineAgentQueryWrapper.lambda().eq(BusProductChannelOfflineAgentCustom::getIncreaseStrategyId, busProductStrategyDTO.getId());
                List<BusProductChannelOfflineAgentCustom> offlineAgentCustomList = busProductChannelOfflineAgentCustomMapper.selectList(offlineAgentQueryWrapper);
                if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(offlineAgentCustomList)) {
                    for (BusProductChannelOfflineAgentCustom offlineAgentCustom : offlineAgentCustomList) {
                        // 选巴士代理列表和系统代理商列表的并集
                        SysAgentQueryListDTO sysBigClientQueryListDTO = sysBigClientQueryListDTOs.stream().filter(sysbig -> sysbig.getId() == offlineAgentCustom.getId()).findFirst().get();
                        if (sysBigClientQueryListDTO != null) {
                            // 当前巴士-线下代理选中-查询加幅规则
                            QueryWrapper<BusProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                            ruleQueryWrapper.lambda().eq(BusProductIncreaseStrategyRule::getCustomId, offlineAgentCustom.getId());
                            busIncreaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                            int remainderNumber = buildRemainderNumber(busIncreaseStrategyRule);
                            if (busIncreaseStrategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT && remainderNumber == 0) {
                                // 余票为0, 代理商失效
                                continue;
                            }
                            BusReservationAgentDTO busReservationAgentDTO = new BusReservationAgentDTO();
                            busReservationAgentDTO.setId(offlineAgentCustom.getId());
                            busReservationAgentDTO.setAgentName(offlineAgentCustom.getAgentName());
                            busReservationAgentDTO.setSaleableType(busIncreaseStrategyRule.getSaleableType());
                            busReservationAgentDTO.setRemainderNumber(remainderNumber);
                            addeAgentAdultPrice(busReservationAgentDTO,
                                    busIncreaseStrategyRule.getPriceType(), busIncreaseStrategyRule.getPrice());
                            addeAgentChildRenPrice(busReservationAgentDTO,
                                    busIncreaseStrategyRule.getPriceType(), busIncreaseStrategyRule.getPrice());
                            reservationAgentDTOList.add(busReservationAgentDTO);
                        }
                    }
                }
            }
        }
        return Result.success(reservationAgentDTOList);
    }

    /**
     * 根据巴士id和用户id，查询用户自营下的加幅后价格和余票信息,售出数量增加
     *
     * @param req
     * @return
     */
    @Override
    public BusPriceRemainderDTO selectSelfPriceRemainderAndLock(BusIncreaseStrategyPriceQueryReq req, Long userId) {
    	int strategyType = req.getAgentId() == null ? 1 : 2;
    	BusPriceRemainderDTO dto = findBusSalePriceInfoHandle(strategyType, req.getBusProductId(), req.getDepartureDate(), req.getAgentId());
    	saveProductSold(dto, req.getTouristNumber(), userId);
    	return dto;
    }

    /**
     * 中汽巴士API产品接入
     */
//    @Transactional(rollbackFor = Exception.class)
    @Override
    @Async
    public Result importRglBusProduct() throws Exception {

        //通过API接口获取中汽班次数据
        List<String[]> list = RlgOrderUtil.getAllSiteList();
        if (CollectionUtils.isEmpty(list)) {
            return Result.failed(SystemError.SYS_411);
        }
        System.out.println("中汽巴士：" + list.size());

//        List<List<String[]>> data = getListIncluderRglList(list, 20);
        
        //初始化配置
        BusInitializationSettings busInitializationSettings = busInitializationSettingsMapper.selectOneByKey("supplier_id", BusConst.SUPPLIER_ID_RGL);
        //负责人
        UserDTO chargePerson = null;
        if (busInitializationSettings.getChargePersonId() != null) {
        	chargePerson = sysUserService.queryCacheUser(busInitializationSettings.getChargePersonId());
        }
        final UserDTO finalChargePerson = chargePerson;
        
        for (String[] arr : list) {
        	batchSaveRlgBusProduct(arr, busInitializationSettings, finalChargePerson);
		}

//        ExecutorService executor = Executors.newFixedThreadPool(data.size() + 2);
//        for (int j = 0; j < data.size(); j++) {
//            List<String[]> newList = data.get(j);
//            Thread thread = new Thread(new Runnable() {
//                @SneakyThrows
//                @Override
//                public void run() {
//                    batchSaveRlgBusProduct(newList, busInitializationSettings, finalChargePerson);
//                }
//            });
//            executor.execute(thread);
//        }
//        executor.shutdown();
        return Result.success();
    }


    /**
     * 中港通巴士API产品接入
     */
//    @Transactional(rollbackFor = Exception.class)
    @Override
    @Async
    public Result importHktBusProduct() throws Exception {
        //通过API接口获取中港通数据
        List<Map> list = HktOrderUtil.getAllSiteList();
        if (CollectionUtils.isEmpty(list)) {
            return Result.failed(SystemError.SYS_411);
        }
        batchsaveHktBusProduct(list);
        return Result.success();
    }

    /**
     * 中港通巴士录入产品信息
     *
     * @param mapList
     */
    public int batchsaveHktBusProduct(List<Map> mapList) throws Exception {
        if (CollectionUtils.isEmpty(mapList)) {
            return -1;
        }
        
        //初始化配置
        BusInitializationSettings busInitializationSettings = busInitializationSettingsMapper.selectOneByKey("supplier_id", BusConst.SUPPLIER_ID_HKT);
        //负责人
        UserDTO chargePerson = null;
        if (busInitializationSettings.getChargePersonId() != null) {
        	chargePerson = sysUserService.queryCacheUser(busInitializationSettings.getChargePersonId());
        }
        
        for (Map map : mapList) {
            String shiftCode = (String) map.get("runId");
            String runTime = (String) map.get("runStartTime");
            runTime = runTime + ":00";
            LocalTime departureTime = LocalTime.parse(runTime, DateTimeFormatter.ofPattern("HH:mm:ss"));

            Object object = map.get("tpa");

            List<Map> tapList = new ArrayList<>();
            if (object instanceof Map) {
                tapList.add((Map) object);
            } else if (object instanceof List) {
                tapList = (List) object;
            }

            if (CollectionUtils.isEmpty(tapList)) {
                continue;
            }
            
            //key：出发站点ID_到达站点ID；value：原数据
            Map<String, Map<String, Object>> stopsMap = new HashMap<>();
            
            for (Map tapMap : tapList) {
            	//票价类型
            	String ticketTypeId = Assist.toString(tapMap.get("ticketTypeId"));
            	//目前只保留1：成人单程；5：儿童单程3-12的产品
            	if (!("9".equals(ticketTypeId) || "14".equals(ticketTypeId)  || "17".equals(ticketTypeId))) {
            		continue;
            	}
            	
            	String beginStopId = Assist.toString(tapMap.get("beginStopId"));
            	String endStopId = Assist.toString(tapMap.get("endStopId"));
            	if (Assist.isBlank(beginStopId) || Assist.isBlank(endStopId)) {
            		continue;
            	}
            	
            	//key：出发站点ID_到达站点ID
            	String stopsKey = beginStopId + "_" + endStopId;
            	Map<String, Object> dataMap = stopsMap.get(stopsKey);
            	if (dataMap == null) {
            		dataMap = new HashMap<>();
            		stopsMap.put(stopsKey, dataMap);
            		
            		dataMap.put("beginStopId", beginStopId);
            		dataMap.put("endStopId", endStopId);
            		dataMap.put("beginStopName", tapMap.get("beginStopName"));
            		dataMap.put("endStopName", tapMap.get("endStopName"));
            		dataMap.put("ticketCategoryId", tapMap.get("ticketCategoryId"));
            	}
            	
            	BigDecimal price = Assist.toBigDecimal(tapMap.get("fee"));
                //成人
                if ("9".equals(ticketTypeId)) {
                	dataMap.put("childPrice", price);
                } else if ("14".equals(ticketTypeId)) {  //小童
                	dataMap.put("adultPrice", price);
				} else if ("17".equals(ticketTypeId)) {  //长者
					dataMap.put("oldPrice", price);
				}
            }
            
            for (Map<String, Object> stopsItemMap : stopsMap.values()) {
            	//成本价格
                BigDecimal adultPrice = (BigDecimal) stopsItemMap.get("adultPrice");
                BigDecimal childPrice = (BigDecimal) stopsItemMap.get("childPrice");
                BigDecimal oldPrice = (BigDecimal) stopsItemMap.get("oldPrice");
                String ticketCategoryId = (String) stopsItemMap.get("ticketCategoryId");
                
                BusProduct busProduct = baseMapper.selectOne(
                        new QueryWrapper<BusProduct>().lambda().eq(BusProduct::getThirdBoardingStationId, stopsItemMap.get("beginStopId"))
                                .eq(BusProduct::getThirdAlightingStationId, stopsItemMap.get("endStopId"))
                                .eq(BusProduct::getShiftCode, shiftCode)
                                .eq(BusProduct::getTicketCategoryId, ticketCategoryId));
                if (Objects.isNull(busProduct)) {
                    //新增
                    busProduct = newCreateEntity(BusProduct.class);
                    busProduct.setProductCode(buildOrderNumber(BusConst.API_IMPORT_USER_ID, LocalDateTime.now()));
                    busProduct.setTicketCategoryId(ticketCategoryId);
                    busProduct.setProductSource(ProductType.API_PRODUCT.getCode());
                    busProduct.setBusCompaniesId(BusConst.COMPANIES_ID_HKT);
                    busProduct.setBusCompaniesName(BusConst.COMPANIES_NAME_HKT);
                    busProduct.setShiftCode(shiftCode);
                    busProduct.setDepartureTime(departureTime);
                    busProduct.setThirdDepartureCityId((String) map.get("fromCityId"));
                    busProduct.setDepartureCityName((String) map.get("fromCityName"));
                    busProduct.setThirdArriveCityId((String) map.get("toCityId"));
                    busProduct.setArriveCityName((String) map.get("toCityName"));
                    busProduct.setThirdBoardingStationId((String) stopsItemMap.get("beginStopId"));
                    busProduct.setBoardingStationName((String) stopsItemMap.get("beginStopName"));
                    busProduct.setThirdAlightingStationId((String) stopsItemMap.get("endStopId"));
                    busProduct.setAlightingStationName((String) stopsItemMap.get("endStopName"));
                    busProduct.setCreateId(BusConst.API_IMPORT_USER_ID);
                    busProduct.setModifiedId(BusConst.API_IMPORT_USER_ID);
                    busProduct.setSaleStatus(1);
                    
                    //填充默认的API初始化设置
                    if (busInitializationSettings != null) {
                    	busProduct.setSupplierId(busInitializationSettings.getSupplierId());
                    	busProduct.setSupplierName(busInitializationSettings.getSupplierName());
                    	busProduct.setChargePersonId(busInitializationSettings.getChargePersonId());
                    	busProduct.setChargePersonName(busInitializationSettings.getChargePersonName());
                    	busProduct.setPriceType(busInitializationSettings.getPriceType());
                    	busProduct.setPrice(busInitializationSettings.getPrice());
                    	busProduct.setPackStatus(busInitializationSettings.getPackStatus());

                    	if (chargePerson != null) {
                    		busProduct.setChargePersonNumber(chargePerson.getEmployeeNumber());
                    		busProduct.setChargePersonDepartment(chargePerson.getDept());
                    	}
                    }
                    busProductMapper.insert(busProduct);

                    //成本
                    BusProductCost busProductCost = new BusProductCost();
                    Long costId = SnowflakeIdWorker.nextId();
                    busProductCost.setId(costId);
                    busProductCost.setBusProductId(busProduct.getId());
                    busProductCost.setCostName("成本");
                    busProductCost.setCurrencyId(BusConst.CURRENCY_ID_HKD);
                    busProductCost.setCurrencyName(BusConst.CURRENCY_NAME_HKD);
                    busProductCostMapper.insert(busProductCost);

                    //成本日期
                    BusProductCostDate busProductCostDate = new BusProductCostDate();
                    busProductCostDate.setId(SnowflakeIdWorker.nextId());
                    busProductCostDate.setCostId(costId);
                    busProductCostDate.setDateBegin(LocalDate.now());
                    busProductCostDate.setDateEnd(LocalDate.now());
                    busProductCostDateMapper.insert(busProductCostDate);
                    
                    //成人
                    if (adultPrice != null) {
                    	batchsaveHktBusProductForCostPrice(costId, adultPrice, BusConst.TOURIST_TYPE_ADULT, BusConst.TOURIST_NAME_ADULT);
                    }
                    //小童
                    if (childPrice != null) {
                    	batchsaveHktBusProductForCostPrice(costId, childPrice, BusConst.TOURIST_TYPE_CHILD, BusConst.TOURIST_NAME_CHILD);
                    }
                    //长者
                    if (oldPrice != null) {
                    	batchsaveHktBusProductForCostPrice(costId, oldPrice, BusConst.TOURIST_TYPE_OLD, BusConst.TOURIST_NAME_OLD);
                    }
                } else {
                    //修改
                	fillUpdateEntity(busProduct);
                    busProduct.setShiftCode(shiftCode);
                    busProduct.setDepartureTime(departureTime);
                    busProduct.setThirdDepartureCityId((String) map.get("fromCityId"));
                    busProduct.setDepartureCityName((String) map.get("fromCityName"));
                    busProduct.setThirdArriveCityId((String) map.get("toCityId"));
                    busProduct.setArriveCityName((String) map.get("toCityName"));
                    busProduct.setThirdBoardingStationId((String) stopsItemMap.get("beginStopId"));
                    busProduct.setBoardingStationName((String) stopsItemMap.get("beginStopName"));
                    busProduct.setThirdAlightingStationId((String) stopsItemMap.get("endStopId"));
                    busProduct.setAlightingStationName((String) stopsItemMap.get("endStopName"));
                    busProductMapper.updateById(busProduct);

                    BusProductCost busProductCost = busProductCostMapper.selectOne(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProduct.getId()));
                    if (!Objects.isNull(busProductCost)) {
//                        BusProductCostDate busProductCostDate = busProductCostDateMapper.selectOne(new QueryWrapper<BusProductCostDate>().lambda().eq(BusProductCostDate::getCostId, busProductCost.getId()));
//                        if (!Objects.isNull(busProductCostDate)) {
//                            busProductCostDate.setDateBegin(LocalDate.now());
//                            busProductCostDate.setDateEnd(LocalDate.now());
//                            busProductCostDateMapper.updateById(busProductCostDate);
//                        }
                        List<BusProductCostPrice> busProductCostPriceList = busProductCostPriceMapper.selectList(new QueryWrapper<BusProductCostPrice>().lambda().eq(BusProductCostPrice::getCostId, busProductCost.getId()));
                        if (!CollectionUtils.isEmpty(busProductCostPriceList)) {
                        	for (BusProductCostPrice busProductCostPrice : busProductCostPriceList) {
                        		//成人
                        		if (BusConst.TOURIST_TYPE_ADULT.equals(busProductCostPrice.getPassengerId())) {
                        			busProductCostPrice.setPrice(adultPrice);
                        		} else if (BusConst.TOURIST_TYPE_CHILD.equals(busProductCostPrice.getPassengerId())) {
                        			busProductCostPrice.setPrice(childPrice);
								} else if (BusConst.TOURIST_TYPE_OLD.equals(busProductCostPrice.getPassengerId())) {
									busProductCostPrice.setPrice(oldPrice);
								} else {
									continue;
								}
                        		busProductCostPriceMapper.updateById(busProductCostPrice);
							}
                        }
                    }
                }

            }
        }
        return 0;
    }
    
    /**
     * 中港通巴士API产品接入，成本价相关
     */
    private void batchsaveHktBusProductForCostPrice(Long costId, BigDecimal price, Long passengerId, String passengerName) {
    	BusProductCostPrice entity = new BusProductCostPrice();
    	entity.setId(newId());
    	entity.setCostId(costId);
    	entity.setPassengerId(passengerId);
    	entity.setPassengerName(passengerName);
    	entity.setPrice(price);
        busProductCostPriceMapper.insert(entity);
	}

    /**
     * 中汽巴士API产品信息拉取
     */
    public int batchSaveRlgBusProduct(String[] array, BusInitializationSettings busInitializationSettings, UserDTO chargePerson) throws Exception {
    	if (Objects.isNull(array)) {
    		return 0;
    	}
    	try {
    		BigDecimal adultPrice = null;
    		BigDecimal childPrice = null;
    		BigDecimal oldPrice = null;

    		String priceInfoStr = array[11];
    		String[] priceInfoArr = priceInfoStr.split(",");
    		for (String priceInfo : priceInfoArr) {
    			BigDecimal price = Assist.toBigDecimal(priceInfo.substring(4, priceInfo.length()));
    			//成人价
    			if (priceInfo.startsWith("4-2")) {
    				adultPrice = price;
    			} else if (priceInfo.startsWith("1-2")) {  //小童价
    				childPrice = price;
    			} else if (priceInfo.startsWith("2-2")) {  //长者价
    				oldPrice = price;
    			}
    		}
    		
    		if (adultPrice == null && childPrice == null && oldPrice == null) {
    			return 0;
    		}
    		
    		String runTime = array[2];
    		runTime = runTime + ":00";
    		LocalTime departureTime = LocalTime.parse(runTime, DateTimeFormatter.ofPattern("HH:mm:ss"));

    		BusProduct busProduct = baseMapper.selectOne(
    				new QueryWrapper<BusProduct>().lambda().eq(BusProduct::getThirdBoardingStationId, array[5])
    				.eq(BusProduct::getThirdAlightingStationId, array[9])
    				.eq(BusProduct::getShiftCode, array[0]));
    		if (Objects.isNull(busProduct)) {
    			//新增
    			busProduct = newCreateEntity(BusProduct.class);
    			busProduct.setProductCode(buildOrderNumber(BusConst.API_IMPORT_USER_ID, LocalDateTime.now()));
    			busProduct.setProductSource(ProductType.API_PRODUCT.getCode());
    			busProduct.setBusCompaniesId(BusConst.COMPANIES_ID_RGL);
    			busProduct.setBusCompaniesName(BusConst.COMPANIES_NAME_RGL);
    			busProduct.setShiftCode(array[0]);
    			busProduct.setDepartureTime(departureTime);
    			busProduct.setThirdDepartureCityId(array[3]);
    			busProduct.setDepartureCityName(array[4]);
    			busProduct.setThirdBoardingStationId(array[5]);
    			busProduct.setBoardingStationName(array[6]);
    			busProduct.setThirdArriveCityId(array[7]);
    			busProduct.setArriveCityName(array[8]);
    			busProduct.setThirdAlightingStationId(array[9]);
    			busProduct.setAlightingStationName(array[10]);
    			busProduct.setCreateId(BusConst.API_IMPORT_USER_ID);
    			busProduct.setModifiedId(BusConst.API_IMPORT_USER_ID);
    			busProduct.setSaleStatus(1);

    			//填充默认的API初始化设置
    			if (busInitializationSettings != null) {
    				busProduct.setSupplierId(busInitializationSettings.getSupplierId());
    				busProduct.setSupplierName(busInitializationSettings.getSupplierName());
    				busProduct.setChargePersonId(busInitializationSettings.getChargePersonId());
    				busProduct.setChargePersonName(busInitializationSettings.getChargePersonName());
    				busProduct.setPriceType(busInitializationSettings.getPriceType());
    				busProduct.setPrice(busInitializationSettings.getPrice());
    				busProduct.setPackStatus(busInitializationSettings.getPackStatus());

    				if (chargePerson != null) {
    					busProduct.setChargePersonNumber(chargePerson.getEmployeeNumber());
    					busProduct.setChargePersonDepartment(chargePerson.getDept());
    				}
    			}
    			busProductMapper.insert(busProduct);

    			//成本
    			BusProductCost busProductCost = new BusProductCost();
    			Long costId = SnowflakeIdWorker.nextId();
    			busProductCost.setId(costId);
    			busProductCost.setBusProductId(busProduct.getId());
    			busProductCost.setCostName("成本");
    			busProductCost.setCurrencyId(BusConst.CURRENCY_ID_HKD);
    			busProductCost.setCurrencyName(BusConst.CURRENCY_NAME_HKD);
    			busProductCostMapper.insert(busProductCost);

    			//成本日期
    			BusProductCostDate busProductCostDate = new BusProductCostDate();
    			busProductCostDate.setId(SnowflakeIdWorker.nextId());
    			busProductCostDate.setCostId(costId);
    			busProductCostDate.setDateBegin(LocalDate.now());
    			busProductCostDate.setDateEnd(LocalDate.now().plusMonths(3));
    			busProductCostDateMapper.insert(busProductCostDate);

    			//成本价格
    			//成人
    			if (adultPrice != null) {
    				batchSaveRlgBusProductForCostPrice(costId, adultPrice, BusConst.TOURIST_TYPE_ADULT, BusConst.TOURIST_NAME_ADULT);
    			}
    			//小童
    			if (childPrice != null) {
    				batchSaveRlgBusProductForCostPrice(costId, childPrice, BusConst.TOURIST_TYPE_CHILD, BusConst.TOURIST_NAME_CHILD);
    			}
    			//长者
    			if (oldPrice != null) {
    				batchSaveRlgBusProductForCostPrice(costId, oldPrice, BusConst.TOURIST_TYPE_OLD, BusConst.TOURIST_NAME_OLD);
    			}
    		} else {
    			//修改
    			fillCreateEntity(busProduct);
    			busProduct.setShiftCode(array[0]);
    			busProduct.setDepartureTime(departureTime);
    			busProduct.setThirdDepartureCityId(array[3]);
    			busProduct.setDepartureCityName(array[4]);
    			busProduct.setThirdBoardingStationId(array[5]);
    			busProduct.setBoardingStationName(array[6]);
    			busProduct.setThirdArriveCityId(array[7]);
    			busProduct.setArriveCityName(array[8]);
    			busProduct.setThirdAlightingStationId(array[9]);
    			busProduct.setAlightingStationName(array[10]);
    			busProductMapper.updateById(busProduct);

    			BusProductCost busProductCost = busProductCostMapper.selectOne(new QueryWrapper<BusProductCost>().lambda().eq(BusProductCost::getBusProductId, busProduct.getId()));
    			if (!Objects.isNull(busProductCost)) {
    				BusProductCostDate busProductCostDate = busProductCostDateMapper.selectOne(new QueryWrapper<BusProductCostDate>().lambda().eq(BusProductCostDate::getCostId, busProductCost.getId()));
    				if (!Objects.isNull(busProductCostDate)) {
    					busProductCostDate.setDateBegin(LocalDate.now());
    					busProductCostDate.setDateEnd(LocalDate.now().plusMonths(3));
    					busProductCostDateMapper.updateById(busProductCostDate);
    				}
    				List<BusProductCostPrice> busProductCostPriceList = busProductCostPriceMapper.selectList(new QueryWrapper<BusProductCostPrice>().lambda().eq(BusProductCostPrice::getCostId, busProductCost.getId()));
    				if (!CollectionUtils.isEmpty(busProductCostPriceList)) {
    					for (BusProductCostPrice busProductCostPrice : busProductCostPriceList) {
    						//成人
    						if (adultPrice != null  && BusConst.TOURIST_TYPE_ADULT.equals(busProductCostPrice.getPassengerId())) {
    							busProductCostPrice.setPrice(adultPrice);
    						} else if (childPrice != null && BusConst.TOURIST_TYPE_CHILD.equals(busProductCostPrice.getPassengerId())) {
    							busProductCostPrice.setPrice(childPrice);
    						} else if (oldPrice != null && BusConst.TOURIST_TYPE_OLD.equals(busProductCostPrice.getPassengerId())) {
    							busProductCostPrice.setPrice(oldPrice);
    						} else {
    							continue;
    						}
    						busProductCostPriceMapper.updateById(busProductCostPrice);
    					}
    				}
    			}
    		}

    	} catch (Exception e) {
    		log.error("中汽巴士API产品信息拉取异常 " + JSON.toJSONString(array), e);
    	}
    	return 0;
    }
    
    /**
     * 中汽巴士API产品信息拉取，产品价相关
     */
    private void batchSaveRlgBusProductForCostPrice(Long costId, BigDecimal price, Long passengerId, String passengerName) {
    	BusProductCostPrice entity = new BusProductCostPrice();
    	entity.setId(newId());
    	entity.setCostId(costId);
    	entity.setPassengerId(passengerId);
    	entity.setPassengerName(passengerName);
    	entity.setPrice(price);
        busProductCostPriceMapper.insert(entity);
	}

    /**
     * 巴士新增产品审批
     *
     * @param req
     * @return
     */
    @Override
    public Result<Void> approval(BusProductAddApprovalReq req, TokenUser tokenUser) {
        //巴士产品
        BusProduct busProduct = busProductMapper.assertExistById(req.getBusinessId());

        //审批
        ApprovalCheckDTO checkDto = sysApprovalService.check(req.getApprovalId(), getTokenUserId(tokenUser),
                req.getApprovalStatus(), req.getComments()).ok();
        if (checkDto == null || !checkDto.getIsFinish()) {
            return newResult();
        }

        fillUpdateEntity(busProduct);
        busProduct.setApprovalStatus(req.getApprovalStatus());
        
        //巴士产品预订信息
        BusProductReservationSettings reservationSettings = busProductReservationSettingsMapper.selectOneByKey("bus_product_id", busProduct.getId());

    	//审批通过
    	if (ApprovalStatus.REVIEW_YES.getCode() == req.getApprovalStatus()) {
    		//立即开售，直接设置产品为售卖状态
    		if (reservationSettings != null && BConst.ONE.equals(reservationSettings.getSaleType())) {
    			busProduct.setSaleStatus(BConst.ONE);
    		}
        } else if (ApprovalStatus.REVIEW_NO.getCode() == req.getApprovalStatus()) {  //审批不通过
        	
        } else {  //撤回
        	
        }

        busProductMapper.updateById(busProduct);

        return newResult();
    }

    /**
     * C端查询巴士预订推荐列表
     *
     * @return
     */
    @Override
    public Result<List<BusB2CRecommendedDTO>> queryB2CRecommendedList(BusB2CRecommendedListQueryReq req) {
        validateArgs(req);

        List<BusB2CRecommendedDTO> list = Assist.defaultList(busProductMapper.queryB2CRecommendedList(req));

        for (BusB2CRecommendedDTO dto : list) {
            if (Assist.isNull(dto.getBusProductId())) continue;

            dto.setPrice(Assist.defaultBigDecimal(dto.getPrice()));

            //api
            if (Constants.API.equals(dto.getProductSource())) {

            } else {  //人工录入
                BusProductStrategyByChannelDTO strategyDto = busProductStrategyMapper.findStrategyListByChannel(dto.getBusProductId(), LocalDate.now(), req.getChannelId());
                if (strategyDto == null || strategyDto.getPrice() == null) continue;

                //数值加幅
                if (BConst.ONE.equals(strategyDto.getPriceType())) {
                    dto.setPrice(dto.getPrice().add(strategyDto.getPrice()));
                } else if (BConst.ONE.equals(strategyDto.getPriceType())) {  //百分比加幅
                    dto.setPrice(dto.getPrice().add(strategyDto.getPrice().multiply(strategyDto.getPrice()).divide(BConst.HUNDRED_BD)));
                }
            }
        }
        return newResult(list);
    }

    /**
     * 查询路线产品列表
     *
     * @return
     */
    @Override
    public List<BusProductCacheDTO> queryBusProductList(List<Long> ids) {
        if(ids == null || ids.size() <= 0){
            return null;
        }

        // 获取产品列表
        LambdaQueryWrapper<BusProduct> productWrapper = Wrappers.<BusProduct>lambdaQuery().eq(BusProduct::getIsDeleted, IsDeletedCode.NO.getCode());
        productWrapper.eq(BusProduct::getSaleStatus, BusSaleStatusCode.VALID.getCode());
        productWrapper.eq(BusProduct::getApprovalStatus, ApprovalStatus.REVIEW_YES.getCode());
        productWrapper.eq(BusProduct::getOnShelfStatus, BusOnShelfStatusCode.UP_SHELF.getCode());
        // 测试用，先写死
        productWrapper.eq(BusProduct::getLineId,"51670730403741696");
        // TODO 正式版使用这个条件
        // productWrapper.in(BusProduct::getLineId,ids);
        List<BusProduct> busProducts = baseMapper.selectList(productWrapper);

        List<BusProductCacheDTO> busProductDTOS = EntityUtil.copyList(busProducts, BusProductCacheDTO.class);

        // 补充产品其余信息
        Assist.forEach(busProductDTOS, product -> {
            // 巴士产品最近7天销量
            Integer count = busOrderService.findBusProduct7DaySaleCount(product.getId());
            product.setSaleCount(count == null ? 0 : count);

            // 巴士产品剩余可销售坐位数
            // 产品加幅策略
            LambdaQueryWrapper<BusProductStrategy> wrapper = Wrappers.<BusProductStrategy>lambdaQuery().eq(BusProductStrategy::getBusProductId, product.getId())
                    .eq(BusProductStrategy::getSelfSalePermissionType, SelfSalePermissionTypeCode.SELF_SALE_PERMISSION_TYPE_2.getCode())
                    .eq(BusProductStrategy::getIsDeleted, IsDeletedCode.NO.getCode());
            List<BusProductStrategy> busProductStrategies = busProductStrategyMapper.selectList(wrapper);
            List<Long> strategiesIds = busProductStrategies.stream().map(item -> item.getId()).collect(Collectors.toList());
            LocalDateTime now = LocalDateTime.now();
            // 产品加幅策略有效期
            if (strategiesIds == null || strategiesIds.size() <= 0) throw new BusinessException(SystemError.BUS_PRODUCT_9032);

            List<BusProductStrategyDate> busProductStrategyDates = busProductStrategyDateMapper.selectList(Wrappers.<BusProductStrategyDate>lambdaQuery().le(BusProductStrategyDate::getDateBegin,now).ge(BusProductStrategyDate::getDateEnd,now).in(strategiesIds != null ,BusProductStrategyDate::getIncreaseStrategyId, strategiesIds));
            List<Long> newStrategiesIds = busProductStrategyDates.stream().map(item -> item.getIncreaseStrategyId()).collect(Collectors.toList());
            // 产品加幅策略渠道
            if(newStrategiesIds == null || newStrategiesIds.size() <= 0) throw new BusinessException(SystemError.BUS_PRODUCT_9033);
            BusProductChannelOnlineSelfPlatform busProductChannelOnlineSelfPlatform = platformMapper.selectOne(Wrappers.<BusProductChannelOnlineSelfPlatform>lambdaQuery().eq(BusProductChannelOnlineSelfPlatform::getChannelId, ChannelMainData.APP_H5.getId()).eq(BusProductChannelOnlineSelfPlatform::getIsDeleted,IsDeletedCode.NO.getCode()).in(BusProductChannelOnlineSelfPlatform::getIncreaseStrategyId, newStrategiesIds));
            // 产品加幅策略规则
            if(busProductChannelOnlineSelfPlatform == null) throw new BusinessException(SystemError.BUS_PRODUCT_9034);
            BusProductIncreaseStrategyRule busProductIncreaseStrategyRule = ruleMapper.selectOne(Wrappers.<BusProductIncreaseStrategyRule>lambdaQuery().eq(BusProductIncreaseStrategyRule::getIncreaseStrategyId, busProductChannelOnlineSelfPlatform.getIncreaseStrategyId()));
            product.setInventory(-1);
            if(busProductIncreaseStrategyRule.getSaleableType().equals(SaleableType.SALEABLE_TYPE_2.getCode())){
                // 产品已售
                BusProductSold busProductSold = soldMapper.selectOne(Wrappers.<BusProductSold>lambdaQuery().eq(BusProductSold::getIncreaseStrategyRule, busProductIncreaseStrategyRule.getId()).eq(BusProductSold::getBusProduct, product.getId()).eq(BusProductSold::getIsDeleted,IsDeletedCode.NO.getCode()));
                // 最大可售數量
                Integer saleableNumber = busProductIncreaseStrategyRule.getSaleableNumber();
                // 已售数
                Integer soldNumber = busProductSold.getSoldNumber();
                product.setInventory(saleableNumber-soldNumber);
                product.setSaleCount(soldNumber);
            }

            // 巴士票价格
            // 产品成本列表
            List<BusProductCost> busProductCosts = busProductCostMapper.selectList(Wrappers.<BusProductCost>lambdaQuery().eq(BusProductCost::getBusProductId, product.getId()));
            List<Long> costIds = busProductCosts.stream().map(cost -> cost.getId()).collect(Collectors.toList());
            // 产品当前时间有效成本
            if(costIds == null || costIds.size() <= 0) throw new BusinessException(SystemError.BUS_PRODUCT_9037);
            BusProductCostDate busProductCostDate = busProductCostDateMapper.selectOne(Wrappers.<BusProductCostDate>lambdaQuery().le(BusProductCostDate::getDateBegin, now).ge(BusProductCostDate::getDateEnd, now).in(costIds != null, BusProductCostDate::getCostId, costIds));
            // 产品成本结果列表
            if(busProductCostDate == null) throw new BusinessException(SystemError.BUS_PRODUCT_9038);
            List<BusProductCostPrice> busProductCostPrices = busProductCostPriceMapper.selectList(Wrappers.<BusProductCostPrice>lambdaQuery().eq(BusProductCostPrice::getCostId, busProductCostDate.getCostId()));
            busProductCostPrices.forEach(price -> {
                if (price.getPassengerId().intValue() == TrainTouristType.ADULT.getType()) {
                    product.setAdultPrice(price.getPrice());
                    product.setAdultPriceId(price.getPassengerId());
                }
                if (price.getPassengerId().intValue() == TrainTouristType.CHILD.getType()) {
                    product.setChildrenPrice(price.getPrice());
                    product.setChildrenPriceId(price.getPassengerId());
                }
            });

        });

        return busProductDTOS;
    }

    /**
     * 运营中心查询巴士产品列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BusProductDTO>> queryProductListForIotc(BusProductListForIotcQueryReq req) {
        IPage<BusProductDTO> page = busProductMapper.queryProductListForIotc(req);
        return newPageResult(page);
    }

    /**
     * 运营中心根据ID查询巴士产品列表
     *
     * @param idList
     * @return
     */
    @Override
    public Result<List<BusProductDTO>> queryProductListByIdForIotc(List<Long> idList) {
        if (Assist.isEmpty(idList))
            return newResult();
        List<BusProductDTO> list = busProductMapper.selectBatchIds(BusProductDTO.class, idList);
        return newResult(list);
    }
    
    /**
     * 查询预订用的代理商信息列表
     * @param req
     * @return
     */
    @Override
    public Result<List<BusProductReservationAgentDTO>> queryReservationAgentList(BusProductReservationAgentQueryReq req, TokenUser tokenUser) {
    	BusProduct busProduct = busProductMapper.assertExistById(req.getId());
    	//成本价
    	List<BusProductCostPriceDTO> priceDTOList = busProductCostMapper.queryPrice(busProduct.getId(), LocalDate.now());
    	List<BusProductReservationAgentDTO> list = new ArrayList<>();
    	
    	//非API产品
        if (!Constants.API.equals(busProduct.getProductSource())) {
        	//预订设置信息
            BusProductReservationSettings reservationSettings = busProductReservationSettingsMapper.selectOneByKey("bus_product_id", busProduct.getId());
            
        	BusProductStrategyDTO busProductStrategy = busProductStrategyMapper.queryBusProductStrategyInfo(busProduct.getId(), req.getQueryDate());
        	if (busProductStrategy == null) {
        		throw new BusinessException(SystemError.BUS_PRODUCT_9038);
        	}
        	
        	//销售渠道类型：禁售
        	if (busProductStrategy.getAgentSalePermissionType() == null || Constants.SALE_CHANNEL_TYPE_DISABLED.equals(busProductStrategy.getAgentSalePermissionType())) {
        		return newResult();
        	} 
        	
        	//加幅规则
        	BusProductIncreaseStrategyRule increaseStrategyRule = null;
        	
        	if (Constants.SALE_CHANNEL_TYPE_ALL.equals(busProductStrategy.getAgentSalePermissionType())) {  //销售渠道类型：所有
        		//加幅规则
        		increaseStrategyRule = ruleMapper.selectById(busProductStrategy.getAgentSalePermissionId());
        		
        		//获取所有代理商
        		List<SysAgentQueryListDTO> agentDtoList = getSysBigClientQueryListDTOS();
                if (Assist.isNotEmpty(agentDtoList)) {
                    for (SysAgentQueryListDTO agentDto : agentDtoList) {
                    	BusProductReservationAgentDTO dto = new BusProductReservationAgentDTO();
                    	dto.setId(agentDto.getId());
                    	dto.setAgentName(agentDto.getGroupCnName());
                    	
                    	//计算价格
                    	BusPriceRemainderDTO busPriceRemainderDTO = findBusSalePriceInfoHandleCalc(busProduct, req.getQueryDate(), increaseStrategyRule, reservationSettings, priceDTOList);
                    	fillBusProductReservationAgentDTO(dto, busPriceRemainderDTO);
                    	
                    	list.add(dto);;
                    }
                }
        	} else if (Constants.SALE_CHANNEL_TYPE_SELECTED.equals(busProductStrategy.getAgentSalePermissionType())) {  //销售渠道类型：选中的
        		List<BusProductChannelOfflineAgentCustom> agentCustomList = busProductChannelOfflineAgentCustomMapper.selectListByKey("increase_strategy_id", busProductStrategy.getId());
        		if (Assist.isNotEmpty(agentCustomList)) {
        			for (BusProductChannelOfflineAgentCustom agentCustom : agentCustomList) {
        				//加幅规则
        	    		increaseStrategyRule = ruleMapper.selectOneByKey("custom_id", agentCustom.getId());
        	    		
        				BusProductReservationAgentDTO dto = new BusProductReservationAgentDTO();
                    	dto.setId(agentCustom.getAgentId());
                    	dto.setAgentName(agentCustom.getAgentName());
                    	
                    	//计算价格
                    	BusPriceRemainderDTO busPriceRemainderDTO = findBusSalePriceInfoHandleCalc(busProduct, req.getQueryDate(), increaseStrategyRule, reservationSettings, priceDTOList);
                    	fillBusProductReservationAgentDTO(dto, busPriceRemainderDTO);
                        
                    	list.add(dto);
    				}
        		}
        	}
        } else {  //API产品
        	//获取所有代理商
    		List<SysAgentQueryListDTO> agentDtoList = getSysBigClientQueryListDTOS();
            if (Assist.isNotEmpty(agentDtoList)) {
                for (SysAgentQueryListDTO agentDto : agentDtoList) {
                	BusProductReservationAgentDTO dto = new BusProductReservationAgentDTO();
                	dto.setId(agentDto.getId());
                	dto.setAgentName(agentDto.getGroupCnName());
                	
                	//计算价格
                	BusPriceRemainderDTO busPriceRemainderDTO = findBusSalePriceInfoHandleCalc(busProduct, req.getQueryDate(), null, null, priceDTOList);
                	fillBusProductReservationAgentDTO(dto, busPriceRemainderDTO);
                	
                	list.add(dto);;
                }
            }
        }

    	return newResult(list);
    }
    
    /**
     * 查询巴士产品售价信息逻辑处理
     * @param strategyType 加幅类型，1：自营；2：代理；3：官方平台；4：第三方平台；
     * @param productId 产品ID
     * @param departureDate 出发日期
     * @param relId 关联ID，strategyType(1：用户ID；2：代理ID；3：渠道ID；4：渠道ID)
     * @return
     */
    @Override
    public BusPriceRemainderDTO findBusSalePriceInfoHandle(int strategyType, Long productId, LocalDate departureDate, Long relId) {
    	validateNotNull(strategyType, productId, departureDate, relId);
    	
    	BusProduct busProduct = busProductMapper.assertExistById(productId);
    	BusProductStrategy busProductStrategy = busProductStrategyMapper.findBusProductStrategy(busProduct.getId(), departureDate);
    	
    	// 获取加幅策略规则
    	BusProductIncreaseStrategyRule increaseStrategyRule = findBusSalePriceInfoByStrategyRule(strategyType, relId, busProductStrategy);
    	
    	//计算价格
    	return findBusSalePriceInfoHandleCalc(busProduct, departureDate, increaseStrategyRule);
    }
    
    /**
     * 查询巴士产品售价信息逻辑处理，计算价格
     * @return
     */
    private BusPriceRemainderDTO findBusSalePriceInfoHandleCalc(BusProduct busProduct, LocalDate departureDate, BusProductIncreaseStrategyRule increaseStrategyRule) {
    	//预订设置信息
    	BusProductReservationSettings reservationSettings = busProductReservationSettingsMapper.selectOneByKey("bus_product_id", busProduct.getId());
    	//成本价
    	List<BusProductCostPriceDTO> priceDTOList = busProductCostMapper.queryPrice(busProduct.getId(), LocalDate.now());
    	
    	return findBusSalePriceInfoHandleCalc(busProduct, departureDate, increaseStrategyRule, reservationSettings, priceDTOList);
    }
    
    /**
     * 查询巴士产品售价信息逻辑处理，计算价格
     * @return
     */
    private BusPriceRemainderDTO findBusSalePriceInfoHandleCalc(BusProduct busProduct, LocalDate departureDate, BusProductIncreaseStrategyRule increaseStrategyRule
    		, BusProductReservationSettings reservationSettings, List<BusProductCostPriceDTO> priceDTOList) {
    	BusPriceRemainderDTO busPriceRemainderDTO = new BusPriceRemainderDTO();
    	//库存数
    	int saleableNumber = -1;
    	
    	busPriceRemainderDTO.setId(busProduct.getId());
    	busPriceRemainderDTO.setDepartureDate(departureDate);
    	busPriceRemainderDTO.setIsLimitTicket(BConst.ONE);
    	busPriceRemainderDTO.setSaleableNumber(0);
    	busPriceRemainderDTO.setRemainderNumber(0);
    	busPriceRemainderDTO.setProductSource(busProduct.getProductSource());
    	
    	//成本价格map，key：旅客类型；value：成本价
    	Map<Long, BigDecimal> costPriceMap = new HashMap<>();
    	if (Assist.isNotEmpty(priceDTOList)) {
    		for (BusProductCostPriceDTO priceDTO : priceDTOList) {
				if (priceDTO.getPassengerId() != null && priceDTO.getPrice() != null) {
					costPriceMap.put(priceDTO.getPassengerId(), priceDTO.getPrice());
				}
			}
    	}
    	
    	//成人成本价
    	BigDecimal adultCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_ADULT);
    	//小童成本价
    	BigDecimal childrenCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_CHILD);
    	//长者成本价
    	BigDecimal oldCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_OLD);
    	
    	if (Assist.isNotEmpty(priceDTOList)) {
    		BusProductCostPriceDTO costPriceDto = Assist.findFirst(priceDTOList);
    		if (costPriceDto != null && costPriceDto.getCostId() != null) {
    			BusProductCost busProductCost = busProductCostMapper.assertExistById(costPriceDto.getCostId());
    			notNull(busProductCost.getCurrencyId(), SystemError.AIREXPRESS_ORDER_60029);
    			
    			//非HKD转换汇率
    			if (!BusConst.CURRENCY_ID_HKD.equals(busProductCost.getCurrencyId())) {
    				BigDecimal rate = mainDataCurrencyService.getPlanneRateById(busProductCost.getCurrencyId());
    				notNull(rate, SystemError.AIREXPRESS_ORDER_60029);
    				adultCostPrice = Assist.calcRateTwo(adultCostPrice, rate);
    				childrenCostPrice = Assist.calcRateTwo(childrenCostPrice, rate);
    				oldCostPrice = Assist.calcRateTwo(oldCostPrice, rate);
    			}
    		}
    	}
    	
    	busPriceRemainderDTO.setAdultPrice(adultCostPrice);
    	busPriceRemainderDTO.setChildrenPrice(childrenCostPrice);
    	busPriceRemainderDTO.setOldPrice(oldCostPrice);
        
        //非API产品
        if (!Constants.API.equals(busProduct.getProductSource())) {
        	//服务费加幅
        	if (reservationSettings != null) {
        		busPriceRemainderDTO.setAdultPrice(addeServicePrice(reservationSettings, adultCostPrice, busPriceRemainderDTO.getAdultPrice()));
        		busPriceRemainderDTO.setChildrenPrice(addeServicePrice(reservationSettings, childrenCostPrice, busPriceRemainderDTO.getChildrenPrice()));
        		busPriceRemainderDTO.setOldPrice(addeServicePrice(reservationSettings, oldCostPrice, busPriceRemainderDTO.getOldPrice()));
        	}

        	//加幅
        	if (increaseStrategyRule != null) {
        		//有限制销售数量
        		if (increaseStrategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT) {
        			// 票数有限制，计算余票数量
        			saleableNumber = increaseStrategyRule.getSaleableNumber() == null ? 0 : increaseStrategyRule.getSaleableNumber();
        		} else {  //无限制销售数量
        			saleableNumber = Assist.defaultInt(busProduct.getInventory());
        		}
        		
        		//价格加幅
        		busPriceRemainderDTO.setAdultPrice(addePrice(increaseStrategyRule, adultCostPrice, busPriceRemainderDTO.getAdultPrice()));
        		busPriceRemainderDTO.setChildrenPrice(addePrice(increaseStrategyRule, childrenCostPrice, busPriceRemainderDTO.getChildrenPrice()));
        		busPriceRemainderDTO.setOldPrice(addePrice(increaseStrategyRule, oldCostPrice, busPriceRemainderDTO.getOldPrice()));

        		busPriceRemainderDTO.setIncreaseStrategyRuleId(increaseStrategyRule.getId());
        		busPriceRemainderDTO.setSaleableNumber(saleableNumber);
        		
        		//计算余票数
            	int remainderNumber = calcRemainderNum(saleableNumber, busProduct.getId(), departureDate);
            	busPriceRemainderDTO.setRemainderNumber(remainderNumber);
        	}
        } else {
        	busPriceRemainderDTO.setIsLimitTicket(BConst.ZERO);
        }

        return busPriceRemainderDTO;

	}
    
    /**
     * 回滚已售数量
     * @param productId
     * @param num
     */
    @Override
    public void rollbackSold(Long productId, int num, LocalDate departureDate, Long userId) {
    	validateNotNull(productId, departureDate);
    	if (num < 0) {
    		return;
    	}
    	
    	BusProductSold entity = busProductSoldMapper.selectOneByKey("bus_product", productId, "sale_date", departureDate);
    	if (entity != null) {
    		num = Assist.defaultInt(entity.getSoldNumber()) - num;
    		if (num < 0) {
    			num = 0;
    		}
    		entity.setSoldNumber(num);
    		fillUpdateEntityUserId(entity, userId);
    		
    		busProductSoldMapper.updateById(entity);
    	}
    }
    
    /**
     * 查询巴士产品售价信息,加幅规则
     * @param strategyType 加幅类型，1：自营；2：代理；3：官方平台；4：第三方平台；
     * @param relId 关联ID，strategyType(1：用户ID；2：代理ID；3：渠道ID；4：渠道ID)
     * @return
     */
    private BusProductIncreaseStrategyRule findBusSalePriceInfoByStrategyRule(int strategyType, Long relId, BusProductStrategy busProductStrategy) {
        BusProductIncreaseStrategyRule increaseStrategyRule = null;
        if (busProductStrategy != null) {
        	//自营
        	if (strategyType == 1) {
        		if (busProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                    // 代理禁售
                } else if (busProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                    //当前机场快线-线下自营所有-获取加幅规则
                    increaseStrategyRule = ruleMapper.selectById(busProductStrategy.getSelfSalePermissionId());
                } else if (busProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                    //当前机场快线-线下自营选中-获取加幅规则
                    QueryWrapper<BusProductChannelOfflineSelfCustom> offlineSelfQueryWrapper = new QueryWrapper<>();
                    offlineSelfQueryWrapper.lambda().eq(BusProductChannelOfflineSelfCustom::getRelationId, relId);
                    offlineSelfQueryWrapper.lambda().eq(BusProductChannelOfflineSelfCustom::getIncreaseStrategyId, busProductStrategy.getId());
                    BusProductChannelOfflineSelfCustom busProductChannelOfflineSelfCustom = busProductChannelOfflineSelfCustomMapper.selectOne(offlineSelfQueryWrapper);
                    if (busProductChannelOfflineSelfCustom != null) {
                        // 当前机场快线-线下自营选中-查询加幅规则
                        QueryWrapper<BusProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                        ruleQueryWrapper.lambda().eq(BusProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineSelfCustom.getId());
                        increaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);

                    } else {
                        SysDepartmentDTO sysDepartmentDTO = sysDepartmentService.queryByUserId(relId);
                        busProductChannelOfflineSelfCustom = findParentDepartmentId(sysDepartmentDTO, busProductStrategy.getId());
                        if (busProductChannelOfflineSelfCustom != null) {
                            // 当前机场快线-线下自营选中-查询加幅规则
                            QueryWrapper<BusProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                            ruleQueryWrapper.lambda().eq(BusProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineSelfCustom.getId());
                            increaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);

                        }
                    }
                }
        	} else if (strategyType == 2) {  //代理
        		// 代理禁售
                if (busProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                } else if (busProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                    // 当前机场快线-线下自营所有-获取加幅规则
                    increaseStrategyRule = ruleMapper.selectById(busProductStrategy.getAgentSalePermissionId());
                } else if (busProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                    //当前机场快线-线下代理选中-获取代理加幅规则列表
                    QueryWrapper<BusProductChannelOfflineAgentCustom> offlineAgentQueryWrapper = new QueryWrapper<>();
                    offlineAgentQueryWrapper.lambda().eq(BusProductChannelOfflineAgentCustom::getIncreaseStrategyId, busProductStrategy.getId());
                    offlineAgentQueryWrapper.lambda().eq(BusProductChannelOfflineAgentCustom::getAgentId, relId);
                    BusProductChannelOfflineAgentCustom busProductChannelOfflineAgentCustom = busProductChannelOfflineAgentCustomMapper.selectOne(offlineAgentQueryWrapper);
                    if (busProductChannelOfflineAgentCustom != null) {
                        // 当前机场快线-线下代理选中-查询加幅规则
                        QueryWrapper<BusProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                        ruleQueryWrapper.lambda().eq(BusProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineAgentCustom.getId());
                        increaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                    }
                }
			} else if (strategyType == 3) {  //官方平台
				BusProductChannelOnlineSelfPlatform onlineSelfPlatform = busProductChannelOnlineSelfPlatformMapper.selectOneByKey("increase_strategy_id", busProductStrategy.getId(), "channel_id", relId);
				if (onlineSelfPlatform != null) {
					increaseStrategyRule = ruleMapper.selectOneByKey("custom_id", onlineSelfPlatform.getId());
				}
 			} else if (strategyType == 4) {  //第三方平台
				
			}
        }
        return increaseStrategyRule;
    }
    
    /**
     * 保存巴士产品已售信息
     *
     * @param saleableNumber         库存数，-1则不限制
     * @param touristNumber
     * @param busProduct
     * @param departureDate
     */
    @Override
    public void saveProductSold(BusPriceRemainderDTO dto, int touristNumber, Long userId) {
    	validateNotNull(dto);
    	
    	int saleableNumber = dto.getSaleableNumber();
        //查询产品已售信息
        BusProductSold entity = busProductSoldMapper.selectOneByKey("bus_product", dto.getId(), "sale_date", dto.getDepartureDate());

        //新增
        if (entity == null) {
            if (saleableNumber != -1 && touristNumber > saleableNumber) {
                // 旅客人数大于余票数量
                throw new BusinessException(SystemError.BUS_ORDER_9019);
            }

            entity = newCreateEntityUserId(BusProductSold.class, null, userId);
            entity.setBusProduct(dto.getId());
            entity.setSoldNumber(touristNumber);
            entity.setSaleDate(dto.getDepartureDate());
            entity.setIncreaseStrategyRule(dto.getIncreaseStrategyRuleId());

            busProductSoldMapper.insert(entity);
        } else {  //修改
            int allNumber = Assist.defaultInt(entity.getSoldNumber()) + touristNumber;
            if (saleableNumber != -1 && allNumber > saleableNumber) {
                // 旅客人数大于余票数量
                throw new BusinessException(SystemError.BUS_ORDER_9019);
            }

            fillUpdateEntityUserId(entity, userId);
            entity.setSoldNumber(allNumber);

            busProductSoldMapper.updateById(entity);
        }
    }
    
    /**
     * 切割list
     *
     * @param matDtlList
     * @param count
     * @return
     */
    public List<List<String[]>> getListIncluderRglList(List<String[]> matDtlList, int count) {
        List<List<String[]>> data = new ArrayList<>();
        int num = matDtlList.size() / count;
        int last = matDtlList.size() % count;
        for (int j = 0; j <= num; j++) {
            List<String[]> newList;
            if (j < num) {
                newList = matDtlList.subList(j * count, ((j + 1) * count));
                data.add(newList);
            } else {
                if (last != 0) {
                    newList = matDtlList.subList(matDtlList.size() - last, matDtlList.size());
                    data.add(newList);
                } else {
                    continue;
                }
            }
        }
        return data;
    }


    /**
     * 新增巴士产品
     *
     * @param busProductReq
     */
    private Result addProductInfo(BusProductReq busProductReq, TokenUser user) {

        List<String> shiftCodeList = new ArrayList<>();
        List<LocalTime> departureTimeList = new ArrayList<>();

        BusshiftReq[] busshiftReqs = busProductReq.getBusshiftReqs();
        for (BusshiftReq busshiftReq : busshiftReqs) {
            //验证班次码是否唯一
            if (Assist.isNotBlank(busshiftReq.getShiftCode())) {
                BusProduct busProductItem = busProductMapper.selectOneByKey("shift_code", busshiftReq.getShiftCode());
                if (busProductItem != null) {
                    //新增巴士
                    if (busProductReq.getId() == null) {
                    	return Result.failed(SystemError.BUS_PRODUCT_9031);
                    } else {  //修改巴士
                        if (!busProductReq.getId().equals(busProductItem.getId())) {
                        	return Result.failed(SystemError.BUS_PRODUCT_9031);
                        }
                    }
                }
            }

            shiftCodeList.add(busshiftReq.getShiftCode());
            departureTimeList.add(busshiftReq.getDepartureTime());
        }

        List<Long> busProductIdList = new ArrayList<>();
        //根据班次新增产品 (一个班次对应一个产品)

        for (int i = 0; i < shiftCodeList.size(); i++) {
            //保存巴士产品信息
            BusProduct busProduct = EntityUtil.copy(busProductReq, BusProduct.class);
            Long busProductId = SnowflakeIdWorker.nextId();
            busProductIdList.add(busProductId);
            busProduct.setProductCode(buildOrderNumber(user.getId(), LocalDateTime.now()));
            busProduct.setShiftCode(shiftCodeList.get(i));
            busProduct.setDepartureTime(departureTimeList.get(i));
            busProduct.setId(busProductId);
            //如果页面没有填写负责人,则默认当前账号
            if (StringUtils.isEmpty(busProduct.getChargePersonId())) {
                busProduct.setChargePersonId(user.getId());
                busProduct.setChargePersonName(user.getUsername());
            }
            busProduct.setOnShelfStatus(BConst.ZERO);
            busProduct.setCreateId(user.getId());
            busProduct.setGmtCreate(LocalDateTime.now());
            busProduct.setIsDeleted(IsDeletedCode.NO.getCode());
            busProduct.setProductSource(ProductType.MANUAL_ENTRY.getCode());
            busProduct.setApprovalStatus(ApprovalStatus.WAIT_SUBMIT.getCode());
            ;
            busProductMapper.insert(busProduct);

            //保存巴士产品座位表
            String seatNumbers = busProductReq.getSeatNumbers();
            List<String> seatNumbersList = Arrays.asList(seatNumbers.split(","));
            for (String seatNumber : seatNumbersList) {
                BusProductSeat busProductSeat = new BusProductSeat();
                busProductSeat.setId(SnowflakeIdWorker.nextId());
                busProductSeat.setProductId(busProductId);
                busProductSeat.setSeatNumber(seatNumber);
                busProductSeatMapper.insert(busProductSeat);
            }

            //保存巴士产品成本信息
            List<BusProductCostReq> busProductCostReqList = busProductReq.getBusProductCostReqList();
            for (BusProductCostReq busProductCostReq : busProductCostReqList) {
                //保存巴士产品成本
                BusProductCost busProductCost = EntityUtil.copy(busProductCostReq, BusProductCost.class);
                Long costId = SnowflakeIdWorker.nextId();
                busProductCost.setId(costId);
                busProductCost.setBusProductId(busProductId);
                busProductCostMapper.insert(busProductCost);

                //保存巴士产品成本日期
                List<BusProductCostDateReq> busProductCostDateReqList = busProductCostReq.getBusProductCostDateReqList();
                for (BusProductCostDateReq busProductCostDateReq : busProductCostDateReqList) {
                    BusProductCostDate busProductCostDate = EntityUtil.copy(busProductCostDateReq, BusProductCostDate.class);
                    busProductCostDate.setId(SnowflakeIdWorker.nextId());
                    busProductCostDate.setCostId(costId);
                    busProductCostDateMapper.insert(busProductCostDate);
                }

                //保存巴士产品成本价格
                List<BusProductCostPriceReq> busProductCostPriceReqList = busProductCostReq.getBusProductCostPriceReqList();
                for (BusProductCostPriceReq busProductCostPriceReq : busProductCostPriceReqList) {
                    BusProductCostPrice busProductCostPrice = EntityUtil.copy(busProductCostPriceReq, BusProductCostPrice.class);
                    busProductCostPrice.setId(SnowflakeIdWorker.nextId());
                    busProductCostPrice.setCostId(costId);
                    busProductCostPriceMapper.insert(busProductCostPrice);
                }
            }

        }

        return Result.success(busProductIdList);
    }


    /**
     * 校验产品信息入参
     *
     * @param busProductReq
     * @param user
     * @return
     */
    private Result checkProductReq(BusProductReq busProductReq, TokenUser user) {
        if (Objects.isNull(user)) {
            return Result.failed(SystemError.USER_1000);
        }
        if (Objects.isNull(busProductReq)) {
            return Result.failed(SystemError.BUS_PRODUCT_9004);
        }
        return null;
    }


    /**
     * 产品成本日期校验
     *
     * @param busProductCostReqList
     * @return
     */
    private Result<Object> checkCostateResult(List<BusProductCostReq> busProductCostReqList) {
        List<BusProductCostDateReq> busProductCostDateReqList = new ArrayList<>();
        // 四种渠道至少有一个在售校验
        for (BusProductCostReq req : busProductCostReqList) {
            busProductCostDateReqList.addAll(req.getBusProductCostDateReqList());
        }
        for (int i = 0; i < busProductCostDateReqList.size(); i++) {
            BusProductCostDateReq productCostDateReq = busProductCostDateReqList.get(i);
            if (productCostDateReq.getDateBegin().isBefore(LocalDate.now())) {
                // 巴士产品加幅策略保存，开始日期不能小于当前日期校验
                return Result.failed(SystemError.BUS_PRODUCT_9024);
            }
            if (i == 0 && productCostDateReq.getDateBegin().isAfter(productCostDateReq.getDateEnd())) {
                // 开始日期必须小于结束日期校验
                return Result.failed(SystemError.BUS_PRODUCT_9021);
            }
            for (int j = 0; j < busProductCostDateReqList.size(); j++) {
                BusProductCostDateReq costDateReqTemp = busProductCostDateReqList.get(j);
                if (i >= j) { // 自身和已经校验过的跳过日期校验
                    continue;
                }
                if (i == 0 && costDateReqTemp.getDateBegin().isAfter(costDateReqTemp.getDateEnd())) {
                    // 开始日期必须小于结束日期校验
                    return Result.failed(SystemError.BUS_PRODUCT_9021);
                }
                if (DateUtil.match(productCostDateReq.getDateBegin(), productCostDateReq.getDateEnd(), costDateReqTemp.getDateBegin(), costDateReqTemp.getDateEnd())) {
                    // 当前日期与其他日期区域重叠校验
                    return Result.failed(SystemError.BUS_PRODUCT_9022);
                }
            }
        }
        return null;
    }


    /**
     * 根据部门信息，递归查询加幅策略-线下自营信息
     *
     * @param sysDepartmentDTO   部门信息
     * @param increaseStrategyId 加幅策略id
     * @return 加幅策略-线下自营信息
     */
    private BusProductChannelOfflineSelfCustom findParentDepartmentId(SysDepartmentDTO sysDepartmentDTO, Long increaseStrategyId) {
        QueryWrapper<BusProductChannelOfflineSelfCustom> offlineSelfQueryWrapper = new QueryWrapper<>();
        offlineSelfQueryWrapper.eq("relation_id", sysDepartmentDTO.getId());
        offlineSelfQueryWrapper.lambda().eq(BusProductChannelOfflineSelfCustom::getIncreaseStrategyId, increaseStrategyId);
        BusProductChannelOfflineSelfCustom busProductChannelOfflineSelfCustom = busProductChannelOfflineSelfCustomMapper.selectOne(offlineSelfQueryWrapper);
        if (busProductChannelOfflineSelfCustom == null && sysDepartmentDTO.getParentId() != null) {
            // 查找上級部門
            SysDepartmentDTO sysDepartmentDTOTemp = sysDepartmentService.queryOne(sysDepartmentDTO.getParentId());
            if (sysDepartmentDTOTemp == null) {
                return null; //没有上级部门，返回null
            }
            busProductChannelOfflineSelfCustom = findParentDepartmentId(sysDepartmentDTOTemp, increaseStrategyId);

        }
        return busProductChannelOfflineSelfCustom;
    }


    /**
     * 推荐价格加幅设置
     *
     * @param recommendedBusDTO
     * @param priceType
     * @param productPrice
     */
    private void buildIncreasePrice(RecommendedBusDTO recommendedBusDTO, Integer priceType, BigDecimal productPrice) {

        // 单程票-成人票数值加幅
        if (priceType != null && priceType == 1) {
            if (productPrice != null) {
                BigDecimal adultOneWayPrice = recommendedBusDTO.getPrice().add(productPrice);
                recommendedBusDTO.setPrice(adultOneWayPrice);
            }

        }
        // 单程票-成人票百分比加幅
        if (priceType != null && priceType == 2) {
            if (productPrice != null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                BigDecimal addPrice = recommendedBusDTO.getPrice().add(recommendedBusDTO.getPrice().multiply(per));
                recommendedBusDTO.setPrice(addPrice);
            }
        }
    }
    
    /**
     * 价格服务费加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addeServicePrice(BusProductReservationSettings rule, BigDecimal costPrice) {
    	if (rule == null)
    		return BigDecimal.ZERO;
        return addePrice(rule.getServiceChargeType(), rule.getServiceChargePrice(), costPrice);
    }
    
    /**
     * 价格服务费加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addeServicePrice(BusProductReservationSettings rule, BigDecimal costPrice, BigDecimal price) {
    	if (price == null) 
    		return null;
    	return price.add(addeServicePrice(rule, costPrice));
    }

    /**
     * 价格加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addePrice(BusProductIncreaseStrategyRule rule, BigDecimal costPrice) {
    	if (rule == null)
    		return BigDecimal.ZERO;
        return addePrice(rule.getPriceType(), rule.getPrice(), costPrice);
    }
    
    /**
     * 价格加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addePrice(BusProductIncreaseStrategyRule rule, BigDecimal costPrice, BigDecimal price) {
    	if (price == null) 
    		return null;
    	return price.add(addePrice(rule, costPrice));
    }

    /**
     * 价格加幅设置
     *
     * @param rulePriceType 加幅价格类型，1：数值加幅；2：百分比加幅；
     * @param rulePrice     加幅值
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addePrice(Integer rulePriceType, BigDecimal rulePrice, BigDecimal costPrice) {
        if (rulePriceType == null || rulePrice == null || costPrice == null) return BigDecimal.ZERO;

        //数值加幅
        if (BConst.ONE.equals(rulePriceType)) {
        	return rulePrice;
        } else if (BConst.TWO.equals(rulePriceType)) {  //百分比加幅
        	return Assist.setScaleTwoUp(Assist.calcPercent(costPrice, rulePrice));
        }

        return BigDecimal.ZERO;
    }

    /**
     * 成人票价格加幅设置
     *
     * @param reservationBusPageDTO
     * @param priceType
     * @param productPrice
     */
    private void addeAdultPrice(ReservationBusPageDTO reservationBusPageDTO, Integer priceType, BigDecimal productPrice) {
        // 单程票-成人儿童票数值加幅
        if (priceType != null && priceType == 1) {
            if (productPrice != null) {
                if (reservationBusPageDTO.getAdultPrice() != null) {
                    BigDecimal adultOneWayPrice = reservationBusPageDTO.getAdultPrice().add(productPrice);
                    reservationBusPageDTO.setAdultPrice(adultOneWayPrice);
                }
            }
        }

        // 单程票-成人儿童票百分比加幅
        if (priceType != null && priceType == 2) {
            if (productPrice != null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                if (reservationBusPageDTO.getAdultPrice() != null) {
                    BigDecimal adultPrice = reservationBusPageDTO.getAdultPrice().add(reservationBusPageDTO.getAdultPrice().multiply(per));
                    reservationBusPageDTO.setAdultPrice(adultPrice);
                }
            }
        }
    }


    /**
     * 儿童票价格加幅设置
     *
     * @param reservationBusPageDTO
     * @param priceType
     * @param productPrice
     */
    private void addeChildRenPrice(ReservationBusPageDTO reservationBusPageDTO, Integer priceType, BigDecimal productPrice) {
        // 单程票-儿童票数值加幅
        if (priceType != null && priceType == 1) {
            if (productPrice != null) {
                if (reservationBusPageDTO.getChildrenPrice() != null) {
                    BigDecimal chilRenOneWayPrice = reservationBusPageDTO.getChildrenPrice().add(productPrice);
                    reservationBusPageDTO.setChildrenPrice(chilRenOneWayPrice);
                }
            }
        }

        // 单程票-成人儿童票百分比加幅
        if (priceType != null && priceType == 2) {
            if (productPrice != null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                if (reservationBusPageDTO.getChildrenPrice() != null) {
                    BigDecimal childRenPrice = reservationBusPageDTO.getChildrenPrice().add(reservationBusPageDTO.getChildrenPrice().multiply(per));
                    reservationBusPageDTO.setChildrenPrice(childRenPrice);
                }
            }
        }
    }


    /**
     * 成人票价格加幅设置
     *
     * @param agentDTO
     * @param priceType
     * @param productPrice
     */
    private void addeAgentAdultPrice(BusReservationAgentDTO agentDTO, Integer priceType, BigDecimal productPrice) {
        // 单程票-成人儿童票数值加幅
        if (priceType != null && priceType == 1) {
            if (productPrice != null) {
                if (agentDTO.getAdultPrice() != null) {
                    BigDecimal adultOneWayPrice = agentDTO.getAdultPrice().add(productPrice);
                    agentDTO.setAdultPrice(adultOneWayPrice);
                }
            }
        }

        // 单程票-成人儿童票百分比加幅
        if (priceType != null && priceType == 2) {
            if (productPrice != null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                if (agentDTO.getAdultPrice() != null) {
                    BigDecimal adultPrice = agentDTO.getAdultPrice().add(agentDTO.getAdultPrice().multiply(per));
                    agentDTO.setAdultPrice(adultPrice);
                }
            }
        }
    }


    /**
     * 儿童票价格加幅设置
     *
     * @param agentDTO
     * @param priceType
     * @param productPrice
     */
    private void addeAgentChildRenPrice(BusReservationAgentDTO agentDTO, Integer priceType, BigDecimal productPrice) {
        // 单程票-儿童票数值加幅
        if (priceType != null && priceType == 1) {
            if (productPrice != null) {
                if (agentDTO.getChildrenPrice() != null) {
                    BigDecimal chilRenOneWayPrice = agentDTO.getChildrenPrice().add(productPrice);
                    agentDTO.setChildrenPrice(chilRenOneWayPrice);
                }
            }
        }

        // 单程票-成人儿童票百分比加幅
        if (priceType != null && priceType == 2) {
            if (productPrice != null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                if (agentDTO.getChildrenPrice() != null) {
                    BigDecimal childRenPrice = agentDTO.getChildrenPrice().add(agentDTO.getChildrenPrice().multiply(per));
                    agentDTO.setChildrenPrice(childRenPrice);
                }
            }
        }
    }


    /**
     * 计算可售数量
     *
     * @param busProductIncreaseStrategyRule
     */
    private int buildRemainderNumber(BusProductIncreaseStrategyRule busProductIncreaseStrategyRule) {
        if (Constants.SALE_TYPE_LIMIT.equals(busProductIncreaseStrategyRule.getSaleableType())) {
            int saleableNumber = busProductIncreaseStrategyRule.getSaleableNumber() == null ? 0 : busProductIncreaseStrategyRule.getSaleableNumber();
            int soldNumber = busProductIncreaseStrategyRule.getSoldNumber() == null ? 0 : busProductIncreaseStrategyRule.getSoldNumber();
            return saleableNumber - soldNumber;
        }
        return 0;
    }

    /**
     * 查询系统代理商列表
     *
     * @return
     */
    private List<SysAgentQueryListDTO> getSysBigClientQueryListDTOS() {
        SysAgentQueryListReq sysBigClientQueryListReq = new SysAgentQueryListReq();
        sysBigClientQueryListReq.setPageNo(1);
        sysBigClientQueryListReq.setPageSize(1000);
        PageResponse<SysAgentQueryListDTO> sysBigClientQueryListDTOPageResponse = sysAgentService.queryAgentListAll(sysBigClientQueryListReq);
        return sysBigClientQueryListDTOPageResponse.getRecords();
    }

    /**
     * 生成巴士产品编码=PB+员工编号+月日4位+时分4位+3位随机数字
     *
     * @param userId
     * @return
     */
    private String buildOrderNumber(Long userId, LocalDateTime nowLocalDateTime) {
        UserDTO userDTO = sysUserService.loadUserByParam(userId, 1);
        String employeeNumber = userDTO.getEmployeeNumber();
        String monthCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getMonthValue()), 2, "0");
        String dayCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getDayOfMonth()), 2, "0");
        String hourCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getHour()), 2, "0");
        String minuteCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getMinute()), 2, "0");
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 100));
        StringBuilder orderNumberSb = new StringBuilder();
        orderNumberSb.append("PB").append(employeeNumber).append(monthCode).append(dayCode).append(hourCode).append(minuteCode).append(randomNumber);
        return orderNumberSb.toString();
    }

    /**
     * 查询
     *
     * @param supplierId
     * @return
     */
    private Long findApiSettingsChargePersonId(Long supplierId) {
        Assist.notNull(supplierId);
        BusInitializationSettings entity = busInitializationSettingsMapper.selectOneByKey(BusInitializationSettings::getSupplierId, supplierId);
        if (entity != null)
            return entity.getChargePersonId();
        return null;
    }
    
    private void fillBusProductReservationAgentDTO(BusProductReservationAgentDTO dto, BusPriceRemainderDTO busPriceRemainderDTO) {
    	dto.setAdultPrice(busPriceRemainderDTO.getAdultPrice());
    	dto.setChildrenPrice(busPriceRemainderDTO.getChildrenPrice());
    	dto.setOldPrice(busPriceRemainderDTO.getOldPrice());
    	dto.setIsLimitTicket(busPriceRemainderDTO.getIsLimitTicket());
    	dto.setRemainderNumber(busPriceRemainderDTO.getRemainderNumber());
	}
}
